在此示例代码中,为什么不
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: //godbolt.org/z/3vqd4ebYM
我希望底部的分配解析param1 = param2;
为 uint16_t,但它却试图复制对象,这不是我想要的。
编译器添加了这个额外的函数。
因为基类
IParameter
具有 const 成员,所以不可复制分配。对于上述代码,编译器不能编译该赋值操作,
param1 = param2
因为删除的赋值运算符是完全匹配,而另一个赋值运算符需要隐式转换。这里的解决方案是取消删除里面的已删除赋值运算符
IParameterBase
godbolt 演示
因为当您写下
param1 = param2
您要传递param2
给赋值的参数operator=
并且param2
是类型的ParameterTx<uint16_t>
,所以只有已删除的副本赋值运算符 = 才是候选项,因为买入的那个using IParameterBase<TYPE>::operator=;
具有类型的参数const uint16_t value
。并且由于基类
IParameter
有一个 const 成员,复制赋值运算符被删除,所以我们出现了提到的错误。为了解决这个问题,您可以在传递之前进行显式转换
param2
,或者允许继承的operator=
(通过using
)参与过载解析,通过取消删除其中一个,就像IParameterBase
在其他答案中所做的那样。