【发布时间】:2021-06-13 09:23:30
【问题描述】:
#include <iostream>
template<typename T>
struct A{};
struct Y{
template<typename T>
bool operator==(A<T>){
std::cout<<"#1\n";
return true;
}
};
template<typename T>
bool operator==(T,Y){
std::cout<<"#2\n";
return true;
}
int main(){
A<int> a;
Y y;
a==y;
}
对于上面的 sn-p,GCC 打印 #2 而 Clang 打印 #1。结果是here。我认为 Clang 是对的,因为 #2 是表达式 a==y 的非重写非成员候选。相反,#1 的综合候选函数也是一个可行的函数。也就是说,重载集将由两个候选者组成,如下所示:
#1'
bool operator==(A<int>,Y); [with T = int] // synthesized candidate for #1
#2'
bool operator==(A<int>,Y);[with T = A<int>]
如果通过重写的候选者([over.match.oper])重载决议恰好考虑了其中一个函数模板,参数顺序相反,则函数参数在其转换模板中的顺序为反转。
P/A 对如下:
transformed type for #1: (A<uniqueT1>, Y) as A
original type for #2: (T, Y) as P
transformed type for #2: (UniqueT2, Y) as A
original type for #1: (Y, A<UniqueT1>) as P
对于上述候选者,模板函数的偏序足以确定哪个是最可行的。这是子弹over.match.best#2.5
对于某些参数 j,ICSj(F1) 是比 ICSj(F2) 更好的转换序列,或者,如果不是这样,
2.5 F1 和 F2 是函数模板特化,根据 [temp.func.order] 中描述的偏序规则,F1 的函数模板比 F2 的模板更特化,或者,如果不是这样,
[2.6 - 2.7]
2.8 F2是重写的候选([over.match.oper])而F1不是
这意味着没有必要进入第 2.8 条。根据上述 P/A 对,#1 至少与#2 一样专业,但#2 至少不如#1 专业;因此,#1' 是偏序中最可行的候选者。所以,Clang 在这里应该是正确的。
但是,请考虑以下变体 sn-p
#include <iostream>
template<class T>
struct A{};
class Y{};
template<class T>
bool operator==(Y,A<T>){
std::cout<<"#1\n";
return true;
}
template<class T>
bool operator ==(T,Y){
std::cout<<"#2\n";
return true;
}
int main(){
A<int> a;
Y y{};
a == y;
}
此时,Clang 和 GCC 都同意 #2 是最可行的候选者。结果是here。但是,在我看来,此示例与第一个示例相似。只是,它将会员候选人更改为非会员候选人。同样,重载集将由两个候选者组成,如下所示:
#1''
bool operator==(A<int>,Y); [with T = int] // synthesized candidate for #1
#2''
bool operator==(A<int>,Y); [with T = A<int>]
在这个例子中,偏序也足以确定哪个候选者是最好的。因此,#1'' 仍然应该是最好的。为什么 Clang 和 GCC 都认为 #2 在这个例子中是最好的?
【问题讨论】:
-
当编译器执行“a==y”行时,我猜它会检查原型 1。“.==(y object)”对于您的第一个示例 2。”== (,
) 对于您的第二个示例,因为第一个原型不存在,我猜这使得 #2 候选成为您的示例中要执行的最佳函数 -
@SantoshSahu c++20 引入了相等运算的新概念,它是一个重写的候选者,它使 c++17 中格式错误的
x==y在 c 中格式正确++20 如果有表达式y==x的候选者。 -
我认为他们可能还没有实现 CWG2445。
-
@T.C.第一个例子似乎 Clang 已经实现了这个提议。但是,对于第二个示例,而 Clang 反映它没有。
-
@T.C. Clang 正确实现了 cwg2445 的example。但是,我不知道为什么 Clang 在我的问题的第二个示例中选择
#2。
标签: c++ templates language-lawyer c++20