gpt4 book ai didi

c++ - 类内声明的友元运算符中左手参数的隐式转换

转载 作者:太空狗 更新时间:2023-10-29 21:19:25 24 4
gpt4 key购买 nike

我正在使用 CRTP 为类提供依赖于模板参数的函数添加,在本例中添加 operator +operator +=,使用模板类 ImplAdd。对于前者,应该对两个参数执行隐式转换,这意味着我必须像这样使用类内友元运算符:

template<class Type, bool active>
struct ImplAdd{
virtual int get_val_() const = 0;
virtual void set_val_(int) = 0;
};

//if activated is true, the operators + and += will be defined
template<class Type>
class ImplAdd < Type, true > {
virtual int get_val_() const = 0;
virtual void set_val_(int) = 0;
Type* this_(){ return (Type*)this; }
public:
Type& operator +=(const Type& x){
set_val_(get_val_() + x.get_val_());
return *this_();
}

//This should enable conversions on the lefthand argument
friend Type& operator+(const Type& lhs, const Type& rhs){
Type ret = lhs;
return ret += rhs;
}
};

这是必需的,因为实际上从 ImplAdd 继承的类定义常量值和这些常量的唯一值类型,很像作用域枚举。

//by using true as the template argument, the operators + and += will be defined
class MyEnum : public ImplAdd<MyEnum, true>{
int get_val_() const override{
return (int)value;
}
void set_val_(int v) override{
value = (ValueT)v;
}
public:
enum class ValueT{
zero, one, two
};
private:
typedef int UnderlyingT;
ValueT value;
public:
static const ValueT zero = ValueT::zero;
static const ValueT one = ValueT::one;
static const ValueT two = ValueT::two;
MyEnum(ValueT x) : value(x){}
MyEnum(const MyEnum& other) : value(other.value){}
};

从我的角度来看,下面的代码现在应该很容易编译,但事实并非如此。

int main(int argc, char* argv[])
{
MyEnum my = MyEnum::zero; //works
my += MyEnum::one; //works
my = MyEnum(MyEnum::zero) + MyEnum::two; //works
my = MyEnum::zero + MyEnum(MyEnum::two); //ERROR C2676
my = MyEnum::zero + MyEnum::two; //ERROR C2676
MyEnum my2 = my + my; //works
return 0;
}

对于标有 C2676 的两行,都会打印以下错误消息:

error C2676: binary '+' : 'const MyEnum::ValueT' does not define this operator or a conversion to a type acceptable to the predefined operator

我做错了什么?将运算符定义为类内友元不是在两个参数上启用隐式转换的常用方法吗?如果没有,在这种情况下我该怎么做?

最佳答案

§13.3.1.2 [over.match.oper]/p3(添加了重点):

for a binary operator @ with a left operand of a type whose cv-unqualified version is T1 and a right operand of a type whose cv-unqualified version is T2, three sets of candidate functions, designated member candidates, nonmember candidates and built-in candidates, are constructed as follows:

  • [...]
  • The set of non-member candidates is the result of the unqualified lookup of operator@ in the context of the expression according to the usual rules for name lookup in unqualified function calls (3.4.2) except that all member functions are ignored. However, if no operand has a class type, only those non-member functions in the lookup set that have a first parameter of type T1 or “reference to (possibly cv-qualified) T1”, when T1 is an enumeration type, or (if there is a right operand) a second parameter of type T2 or “reference to (possibly cv-qualified) T2”, when T2 is an enumeration type, are candidate functions.
  • [...]

用简单的英语来说,如果两个操作数都没有类类型,那么您需要在枚举操作数上精确匹配才能考虑重载,这就是为什么 my = MyEnum::zero + MyEnum::二; 不起作用。 my = MyEnum::zero + MyEnum(MyEnum::two);,奇怪的是,在 GCC 中编译而不是 Clang。我找不到任何使它不合法的东西,所以我怀疑这可能是编译器错误。

关于c++ - 类内声明的友元运算符中左手参数的隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27361230/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com