c++templatesinheritanceoperator-overloading

Using base class operator= overload not building


In this example code, why isn't using IParameterBase<TYPE>::operator=; working, and the base class assignment operator working?

I recently changed to this templated version, previously I had written individual type classes where this mechanism worked.

#include <cstdint>
#include <cstddef>
    
    class IParameter
    {
    public:
        explicit IParameter(const size_t size) : size_{size} {};
        virtual ~IParameter() = default;

        virtual void copy(uint8_t*& addr) = 0;
    private:
        const size_t size_;
    };

    template <class TYPE>
    class IParameterBase : public IParameter
    {
    public:
        explicit IParameterBase(const TYPE value) : IParameter{sizeof(TYPE)}, value_{value} {};
        ~IParameterBase() = default;

        virtual void update(const TYPE value) = 0;

        operator auto() const {return get();};

        TYPE operator= (const TYPE value) { update(value); return get(); };

        TYPE get() const {return value_;};

        protected:
        TYPE value_;
    };

    template <class TYPE>
    class ParameterTx : public IParameterBase<TYPE>
    {
    public:
        explicit ParameterTx(const TYPE value) : IParameterBase<TYPE>{value} {};

        using IParameterBase<TYPE>::operator=;

        void copy(uint8_t*& addr) override
        {
            /* copy stuff */
        }
        void update(const TYPE value) override
        {
            this->value_ = value;
        }
    };


int main ()
{
    ParameterTx<uint16_t> param1{0};
    ParameterTx<uint16_t> param2{1};

    param1 = 16;
    param2 = 5;

    param1 = param2;
}

Code here: https://godbolt.org/z/3vqd4ebYM

I expect the assignment at the bottom param1 = param2; to resolve to uint16_t, instead it's trying to copy the object, which is not what I want.


Solution

  • the compiler slipped in this extra function.

    template <class TYPE>
    class IParameterBase : public IParameter
    {
    public:
    ...
      TYPE operator= (const TYPE value) { update(value); return get(); };
    
       // this next one
      IParameterBase<TYPE>& operator= (const IParameterBase<TYPE>& value) = delete;
    ...
    };
    

    because the base IParameter is not copy-assignable as it has a const member.

    With the code above the compiler is not allowed to compile the assignment param1 = param2 because the deleted assignment operator is an exact match, while the other one requires an implicit conversion.

    the solution here is to undelete the deleted assignment operator inside IParameterBase

    TYPE operator= (const IParameterBase<TYPE>& value) 
    { update(value.value_); return this->get(); };
    

    godbolt demo