C++ 类内友元运算符不';我似乎没有参与解决过载问题
在编写一个CRTP模板,使类能够基于模板参数为C++ 类内友元运算符不';我似乎没有参与解决过载问题,c++,operator-overloading,overloading,friend,C++,Operator Overloading,Overloading,Friend,在编写一个CRTP模板,使类能够基于模板参数为operator+提供重载时,我发现,如果类内友元运算符的任何参数都不是它在中定义的类的类型,则它似乎不会参与重载解析 简而言之: enum class FooValueT{ zero, one, two }; class Foo{ FooValueT val_; public: Foo(FooValueT x) : val_(x){}; Foo& operator+=(Foo other){
operator+
提供重载时,我发现,如果类内友元运算符的任何参数都不是它在中定义的类的类型,则它似乎不会参与重载解析
简而言之:
enum class FooValueT{
zero, one, two
};
class Foo{
FooValueT val_;
public:
Foo(FooValueT x) : val_(x){};
Foo& operator+=(Foo other){
val_ = (FooValueT)((int)val_ + (int)other.val_);
return *this;
}
//overload for Foo+Foo, FooValueT+Foo and Foo+FooValueT
friend Foo operator+(Foo lhs, Foo rhs){
Foo ret = lhs;
return ret += lhs;
}
//explicit overload for FooValueT+FooValueT
friend Foo operator+(FooValueT lhs, FooValueT rhs){
return (Foo)lhs + (Foo)rhs;
}
};
看起来有点过分,但这是必要的,因为foomy=FooValueT::one+FooValueT::zero
应该是一个有效的表达式,如果没有任何参数具有类类型,则它们不会进行隐式转换,正如在我前面的问题中所解释的那样
尽管做出了所有这些努力,以下代码仍无法编译:
int main(int argc, char* argv[])
{
Foo my = FooValueT::zero;
my += FooValueT::one;
my = Foo(FooValueT::zero) + FooValueT::two;
my = FooValueT::zero + Foo(FooValueT::two);
my = FooValueT::zero + FooValueT::two; //error C2676
return 0;
}
错误消息是:
error C2676: binary '+' : 'FooValueT' does not define this operator or a conversion to a type acceptable to the predefined operator
一旦我将操作符完全移出类,或者将其声明为友元但在类外定义它,这个问题就会解决。当Foo
是要从中派生的模板类时,这两个选项似乎都不可行
据我所知,operator+(ValueT,ValueT)
的上述类内友元定义应该创建一个自由函数,就像此定义一样:
class Foo{
/*All the stuff you saw previously*/
friend Foo operator+(FooValueT lhs, FooValueT rhs);
};
Foo operator+(FooValueT lhs, FooValueT rhs){
return (Foo)lhs + (Foo)rhs;
}
我哪里出了问题?与常规自由好友函数相比,函数的类内好友定义是否改变了重载解析规则?n3376 11.3/6-7
函数可以在类的友元声明中定义,如果和
仅当类是非本地类(9.8)时,函数名为
不合格,且函数具有命名空间范围
这样的函数是隐式内联的在中定义的友元函数
类位于定义它的类的(词法)范围内。A.
类外定义的友元函数不是(3.4.1)。
在您的情况下,运算符在类作用域中,当您尝试调用此运算符时,ADL将不会尝试在类中查找运算符,因为两个参数都不具有此类的类型。只需编写自由函数(或声明不在类中的friend)
看起来你不能这样做,类中友元函数声明的问题是函数将在类范围内,但你不能将此函数声明为自由友元函数,因为编译器无法推断返回类型参数。@JoachimPileborg,即使函数参数和返回类型依赖于模板参数,并且不包含模板类本身的任何概念?如果是,语法是什么?编辑:Nevermind,找到了它,它似乎很有用。在类中移动枚举类型也可以修复它,但我怀疑它在这里是否有用。请尝试将“using Foo::operator+”添加到class@T.C.你是对的,这对我没有帮助。尽管如此,这还是很有趣的。@Asaf这根本不起作用,为什么要这样做呢
operator+
不是Foo
的成员,限定名Foo::operator+
无效。7.3.1.2/3是更相关的引用。请引用我自己的话:“一旦我将操作符完全移出类,或者将其声明为友元但在类外定义它,这个问题就会解决。当Foo
是要从中派生的模板类时,这两个选项似乎都不可行。“因此,虽然这是一个正确的答案,但它并不能解决我的问题。@iFreilicht模板类有什么问题?你能详细说明吗?用一个简单的示例。模板类ImplAdd{friend Type operator+(ValueT,ValueT)};//我在这里写什么?
在从ImplAdd
派生Foo
后,当尝试调用operator+(FooValueT,FooValueT)
时,ImplAdd的模板参数无法从调用中推导出来。感谢您的编辑,但这在MSVC中都不起作用(错误信息仍然是一样的),我也不明白为什么要在gcc+中编译。这与您发布的确切引用不矛盾吗?