在此示例代码中,为什么不
using IParameterBase<TYPE>::operator=;
工作,而基类赋值运算符工作?

我最近改用了这个模板版本,以前我曾编写过可以发挥此机制作用的单独类型类。

#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;
}

代码在此:
https:

我希望底部的分配解析param1 = param2;为 uint16_t,但它却试图复制对象,这不是我想要的。

7

  • “我希望任务在底部…”请将“底部”更改为您所指的确切陈述。


    – 


  • 1
    “相反,它试图复制对象….”始终将完整错误与问题一起发布。很多时候答案就在错误中。


    – 


  • 1
    问题是它IParameter有一个 const 成员,这使得它无法分配。


    – 

  • 1
    @molbdnilo OP 似乎已经知道了。他们问为什么选择已删除的版本而不是该 using IParameterBase<TYPE>::operator=版本。


    – 


  • 目前还不清楚“[…] 解析为 uint16_t,而是尝试复制对象”是什么意思。


    – 


最佳答案
2

编译器添加了这个额外的函数。

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;
...
};

因为基类IParameter具有 const 成员,所以不可复制分配。

对于上述代码,编译器不能编译该赋值操作,param1 = param2因为删除的赋值运算符是完全匹配,而另一个赋值运算符需要隐式转换。

这里的解决方案是取消删除里面的已删除赋值运算符IParameterBase

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

2

  • 我明白了,所以在这种情况下,LHS 正在伸手并从 RHS 中获取值。我将稍微调整一下,将 value.value_ 更改为 value.get()


    – 


  • @PaulSheppard 是的,它正在从 RHS 复制值。


    – 


为什么使用 IParameterBase::operator=; 不起作用,而基类赋值运算符起作用?而是尝试复制对象。

因为当您写下param1 = param2您要传递param2给赋值的参数operator=并且param2是类型的ParameterTx<uint16_t>,所以只有已删除的副本赋值运算符 = 才是候选项,因为买入的那个using IParameterBase<TYPE>::operator=;具有类型的参数const uint16_t value

并且由于基类IParameter有一个 const 成员,复制赋值运算符被删除,所以我们出现了提到的错误。

为了解决这个问题,您可以在传递之前进行显式转换param2,或者允许继承的operator=(通过using)参与过载解析,通过取消删除其中一个,就像IParameterBase在其他答案中所做的那样。