Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类内友元运算符不';我似乎没有参与解决过载问题_C++_Operator Overloading_Overloading_Friend - Fatal编程技术网

C++ 类内友元运算符不';我似乎没有参与解决过载问题

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){

在编写一个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;
    }
};
看起来有点过分,但这是必要的,因为
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+中编译。这与您发布的确切引用不矛盾吗?