6

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.

6
  • "I expect the assignment at the bottom..." Kindly change "bottom" to the exact statement you're referring to. Commented Oct 3, 2024 at 11:48
  • 1
    "instead it's trying to copy the object...." Always post complete error along with your question. Many times the answer is in the error. Commented Oct 3, 2024 at 11:50
  • 1
    The problem is that IParameter has a const member, which makes it unassignable. Commented Oct 3, 2024 at 11:57
  • 1
    @molbdnilo OP already seem to know that. They're asking why the deleted version is choosen over the using IParameterBase<TYPE>::operator= version. Commented Oct 3, 2024 at 11:58
  • The answer is when you wrote param1 = param2 you're passing param2 which is of type ParameterTx<uint16_t> so only the deleted copy assignment operator= is a candidate because the one bought in by using IParameterBase<TYPE>::operator=; has a parameter of type const uint16_t value Commented Oct 3, 2024 at 12:01

2 Answers 2

7

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

Sign up to request clarification or add additional context in comments.

2 Comments

I see, so in this case the LHS is reaching in and taking the value from the RHS. I'll adapt that slightly and change value.value_ to value.get()
@PaulSheppard it is copying the value from the RHS, yes.
4

why isn't using IParameterBase::operator=; working, and the base class assignment operator working? instead it's trying to copy the object.

Because when you wrote param1 = param2 you're passing param2 to the parameter of the assignment operator= and param2 is of type ParameterTx<uint16_t> so only the deleted copy assignment operator= is a candidate because the one bought in by using IParameterBase<TYPE>::operator=; has a parameter of type const uint16_t value.

And since the copy assignment operator is deleted because the base IParameter has a const member, we have the mentioned error.

To solve this you can either do explicit cast before passing param2 or allow the inherited operator=(via using) take part into overload resolution by undeleting the one from IParameterBase as done in other answer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.