简体   繁体   English

为什么不能定义一元运算符,然后在MSVC的模板类中声明具有相同名称的友元二进制运算符?

[英]Why cannot I define a unary operator and then declare a friend binary operator with same name in a template class in MSVC?

Consider such code: 考虑这样的代码:

template<typename S>
class C;

template<typename S>
C<S> operator-(C<S> lhs, C<S> rhs);

template<typename S>
class C
{
public:
    C operator-() { return *this; }
    friend C operator-<S>(C lhs, C rhs);//error on this line
};

template<typename S>
C<S> operator-(C<S> lhs, C<S> rhs) { return C<S>(); }

int main(int argc, char** argv)
{
    C<int> a,b;
    a-b;
    return 0;
}

This gives me 6 errors in MSVC. 这给了我MSVC 6错误。 But if I move the definition of C operator-() after the friend declaration, it compiles. 但是,如果在朋友声明之后移动C operator-()的定义,它将进行编译。 If I change the class to an untemplated class, it compiles. 如果将类更改为未模板化的类,则会进行编译。 And this seems to compiles in g++ too. 这似乎也可以在g ++中编译。 (I have no g++ installed, based on https://wandbox.org/ ) (基于https://wandbox.org/我没有安装g ++)

So what's wrong here? 那这怎么了?

I have found some useful information data here . 在这里找到了一些有用的信息数据。 The problem is that the member operator unary minus hides the global binary subtract. 问题是成员运算符一元减号隐藏了全局二进制减法。 So I have to declare the friend with 所以我必须与

friend C<S> (::operator-<S>)(C<S> lhs, C<S> rhs);

to explicitly ask for operator- in the global scope: in c++ name lookup happens before type check. 明确要求在全局范围内使用operator-:在c ++名称中,在类型检查之前进行查找。

Besides, as the friend is not part of the class (I suppose that's the reason), it is a must to write template argument after the return type and parameter type. 此外,由于朋友不是类的一部分(我想是原因),因此必须在返回类型和参数类型之后编写模板参数。 Without them (ie friend C (::operator-<S>)(C lhs, C rhs); ) it still works in MSVC, but not with g++. 没有它们(例如, friend C (::operator-<S>)(C lhs, C rhs); ),它们仍然可以在MSVC中工作,但不适用于g ++。

This line is messing your code: 这行弄乱了您的代码:

C operator-() { return *this; }

Remove it and your code compiles (well, change a+b to ab ). 删除它,然后代码会编译(好,将a+b更改为ab )。

It tries to overload an arithmetic operator with no operands . 它试图重载没有操作数的算术运算符。 Arithmetic operators have one operand if declared inside a class, or two operands if declared outside. 如果在类中声明算术运算符,则具有一个操作数;如果在类外部声明,则算术运算符具有两个操作数。

From operator overloading doc : 运算符重载doc

It is not possible to change the precedence, grouping, or number of operands of operators. 不能更改运算符的优先级,分组或操作数的数量。

The friend declaration, despite of being declared inside the class is not a member function of the class. 尽管在类中声明了friend声明,但它不是该类的成员函数

For much more info about operator oveloading see this question 有关操作员oveloading的更多信息,请参阅此问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM