类内好友运算符似乎不参与重载解析
In-class friend operator doesn't seem to participate in overload resolution
在编写一个 CRTP 模板以使类能够根据模板参数为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;
}
};
看起来有点过分,但这是必要的,因为Foo my = 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( 时,函数名称为 不限定,并且函数具有命名空间范围。
这样的函数是隐式内联的。在 类位于定义它的类的(词法(范围内。一个 在类外部定义的友元函数不是 (3.4.1(。
在您的情况下,运算符在类范围内,当您尝试调用此运算符时,ADL 不会尝试在类中查找运算符,因为这两个参数都没有此类的类型。只需编写自由函数(或声明不在类中的好友(。
似乎你不能做这样的事情,在类中声明友元函数的问题在于该函数将在类范围内,但你不能将此函数声明为自由友元函数,因为编译器无法推断返回类型参数。
相关文章:
- 继承函数的重载解析
- 你能重载对象变量名本身返回的内容吗
- 从父命名空间重载类型
- 使用C++中的模板和运算符重载执行矩阵运算
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 重载操作程序时出错>>用于类中的字符串 memebr
- 一个关于在C++中重载布尔运算符的问题
- 不同翻译单元中不可重载的非内联函数定义
- 为什么使用SFINAE而不是函数重载
- 为什么我不能在 C++ 中的特定函数重载中调用同一函数的任何其他重载?
- 将重载的成员函数传递给函数模板
- 好友与成员运算符重载的优先级
- 重载运算符>类模板中的好友
- C++:制作模板运算符 = 重载好友
- 模板好友函数重载
- 重载运算符<<用于模板类.即使使用好友关键字也无法获得私人会员
- 尝试以好友身份重载流时无法访问<<成员函数?
- 使用好友和成员函数的运算符重载
- 类内好友运算符似乎不参与重载解析
- 将cout重载为非好友助手运算符