简体   繁体   English

运算符重载解析在名称空间内工作

[英]Operator overload resolution work within namespaces

namespace A{
   struct A{
    inline void operator+(const int B) {};   // 1)
 };
    inline void operator+(const A& a,const int B) {};  // 2)
 }

    inline void operator+(const A::A& a,const int B) {};  // 3)

int main()
{
 A::A a;
 a+1; // compile questions
 return 1;
}

The above codes can be compiled without any problem. 以上代码可以毫无问题地进行编译。

But if 1) is commented, it fails to be compiled due to "ambiguous overload for 'operator+' in 'a + 1'" at 2) and 3). 但是,如果对1)进行了注释,则由于“在2)和3)中“'a + 1'中'operator +'的重载不明确”而无法编译。 I can understand that the operator+ is first searched in class, there is the reason if 1) is not commented, no problem to be compiled. 我可以理解,运算符+是在类中首先搜索到的,这是因为如果1)没有被注释,则编译没有问题。 Aren't I right? 我不是吗

Main question: If 1) is commented, why compiler has found one matched operator+, it continues to find the others? 主要问题:如果注释了1),为什么编译器找到了一个匹配的运算符+,却继续找到其他运算符? I am also curious that which one should be found first as well. 我也很好奇应该首先找到哪个。 (I thought it should stopped immediately based on the information How does the operator overload resolution work within namespaces? ) (我认为应根据以下信息立即停止操作:运算符重载解析如何在名称空间中工作?

Second questions: 第二个问题:

namespace A{
   struct A{
    inline void operator+(const long int B) {};   // 4), the input parameter type has been changed to long int
 };
    inline void operator+(const A& a,const int B) {};  // 5)
    void test();
 }

    inline void operator+(const A::A& a,const int B) {};  // 6)

 void A::test()
 {
    A a; // a)
    a+ 1; 
 }


int main()
{
 A::A a;
 a+1;  // b) 
 return 1;
}

Compilation ambiguous error at a) due to 4) and 5). 由于4)和5),a)处的编译歧义错误。

Compilation ambiguous error at b) due to 4) ,5) and 6). 由于4),5)和6),b)处的编译歧义错误。

Question i) 问题i)

For a) and b) , why compiler has already found operator+ with (const long int input parameter type ) at 4), which is member operator funciton in struct A, it still keeps going to find out others. 对于a)和b),为什么编译器已经在4)中找到了带有(const long int输入参数类型)的operator +,它是结构A中的成员运算符,所以它仍然会继续寻找其他运算符。 In my mind, compiler should stopped there gives out the type error information. 在我看来,编译器应该停止在那里给出类型错误信息。 It should be the same as in the case the memeber fucntion's input parameter type is exactly matched, it stops searching for others. 它应与成员功能的输入参数类型完全匹配的情况相同,它会停止搜索其他参数。

Question 2) 问题2)

I thought the compiler should stop at 4) and give out type error information. 我认为编译器应在4)停止并给出类型错误信息。 In the case it continues, why member function overloading function (long int) has the same resolution ranking as non-memmber with exact matched input parameter ? 如果继续,为什么成员函数重载函数(long int)与输入参数完全匹配的非成员具有相同的分辨率等级? In this case, I thought the non-member case with exact matched input parameter should win if compiler decides to continue searching, which makes more sense. 在这种情况下,我认为如果编译器决定继续搜索,则输入参数完全匹配的非成员情况应该会获胜,这更有意义。

It's explained in C++ standard, section "13.3.1.2 Operators in expressions", point 2: 在C ++标准的“ 13.3.1.2表达式中的运算符”部分,第2点中对此进行了说明:

If either operand has a type that is a class or an enumeration, a user-defined operator function might be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator. 如果任何一个操作数的类型是类或枚举,则可能会声明一个用户定义的运算符函数来实现该运算符,或者可能需要用户定义的转换才能将该操作数转换为适合于在运算符中。

According to the further explanations a+1 would be transformed in either a.operator+(1) (member function) or operator+(a,1) (non-member function). 根据进一步的解释, a+1将转换为a.operator+(1) (成员函数)或operator+(a,1) (非成员函数)。

The point 3 explains that: 第3点说明:

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: 对于二进制运算符@,其左操作数的类型为cv不合格版本为T1,右操作数的类型为cv不合格版本为T2,这三组候选函数包括指定的候选函数,非成员候选函数和内置函数候选人,其构成如下:

  • if T1 is a complete class type, the set of member candidates is the result of the qualified lookup of T1::operator@ 如果T1是完整的类类型,则候选成员集是对T1 :: operator @进行合格查找的结果

This explains why (1) is choosen when it's active. 这解释了为什么在活动状态下选择了(1)。 When you comment it out, the set of member candidates is empty. 当您将其注释掉时,候选成员集为空。 Then, according to the next bullet in the standard: 然后,根据标准中的下一个项目符号:

  • 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 except that all member functions are ignored. 非成员候选集是在表达式的上下文中根据不合格函数调用中用于名称查找的常规规则对操作符@进行不合格查找的结果,只是忽略了所有成员函数。

According to these rules, as your expression is in main() and not included in a namespace, the two candidate functions are found and of course, it's ambiguous for the compiler. 根据这些规则,由于您的表达式位于main()而不包含在名称空间中,因此找到了两个候选函数,当然,这对于编译器来说是模棱两可的。

You could easily disambiguate which operator to use with the following statement in main() : 您可以通过main()的以下语句轻松区分要使用的运算符:

    using A::operator+;

If you would have the expression a+1 inside a function in namespace A there would be no ambiguity either : 如果您在名称空间A的函数中包含表达式a + 1,那么也不会存在歧义:

//...your code preceding the main()
namespace A{  // reopen the namespace 
    void f()
    {
        A a;
        a + 1; // version of the namespace is taken first 
    }
}

The operator definied in the namespace would be taken first (as long as (1) remains commented out). 只要在名称空间中定义的运算符将被首先采用(只要(1)仍被注释掉)。

About second question 关于第二个问题

First remark: if the member function would use int as argument, like the two other functions, there would be no ambiguity, and (4) would be chosen for both expressions as in your first question. 首先说明:如果成员函数像其他两个函数一样将int用作参数,则不会有歧义,并且将与第一个问题一样为这两个表达式选择(4)。 The same would happen if all three functions would use long as argument instead of int . 如果所有三个函数都使用long作为参数而不是int则会发生同样的情况。

The fact that you have the same name but different arguments requires us to digg more in depth of name hiding and overloading rules in section 13.3.1.2 of standard. 名称相同但参数不同的事实要求我们在标准的13.3.1.2节中更深入地研究名称隐藏和重载规则。 The point 6 states that : 第6点指出:

The set of candidate functions for overload resolution is the union of the member candidates, the non-member candidates, and the built-in candidates. 用于重载解决方案的候选函数集是成员候选者,非成员候选者和内置候选者的并集。 The argument list contains all of the operands of the operator. 参数列表包含运算符的所有操作数。 The best function from the set of candidate functions is selected according to 13.3.2 and 13.3.3 根据13.3.2和13.3.3从候选函数集中选择最佳函数

13.3.2 is about viable functions, ie having the same number of arguments and an implicit conversion between the argument type and the parameter type. 13.3.2是关于可行的函数的,即具有相同数量的参数以及参数类型与参数类型之间的隐式转换。

13.3.3 is about selecting the best viable function. 13.3.3关于选择最佳可行功能。 " If there is exactly one viable function that is a better function than all other viable functions, then it is the one selected by overload resolution; otherwise the call is ill-formed ". 如果恰好有一个可行的功能比所有其他可行的功能要好,那么它就是由过载解析选择的功能;否则调用格式不正确 ”。

In the case of (a) there are two best viable functions: the member function with a conversion (4) or the non member function without conversion, within the namespace (5) (because test() is in the namespace). 在(a)的情况下,有两个最佳可行的函数:在名称空间(5)中具有转换的成员函数(4)或没有转换的非成员函数(因为test()在名称空间中)。 Hence the ambiguity. 因此,模棱两可。

In the case of b) there are three best viable functions: the same as in (a) as well as (6). 对于b),存在三个最佳可行功能:与(a)和(6)中相同。 But note that , if (6) would use long, it would not cause an ambiguity since the member function would win. 但是请注意,如果(6)将使用long,则不会引起歧义,因为成员函数将获胜。

Resolving a call to function +, a compiler performs an argument dependent lookup which includes construction of a set of candidate functions and overload resolution. 解决对函数+的调用,编译器执行基于参数的查找,其中包括一组候选函数的构造和重载解析。 The candidate functions include member, non-member and built-in candidates, and non-member candidates include all declarations found by the unqualified name lookup. 候选函数包括成员,非成员和内置候选,非成员候选包括通过不合格名称查找找到的所有声明。 If 1 is not commented, normal lookup of a qualified name finds a matching class member function. 如果未注释1,则正常查找合格名称会找到匹配的类成员函数。 If 1 is commented, the ADL looks in the set of namespaces associated with the types of the function arguments. 如果注释为1,则ADL查找与函数参数类型关联的名称空间集合。 It finds two candidates which are both viable functions and have identical ranking of implicit conversion sequences, which results in the ambiguous overload error. 它找到两个候选函数,它们都是可行的函数,并且具有相同的隐式转换序列等级,从而导致模棱两可的过载错误。 The same example is given here http://en.wikipedia.org/wiki/Argument-dependent_name_lookup#Criticism 此处提供了相同的示例http://en.wikipedia.org/wiki/Argument-dependent_name_lookup#Criticism

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

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