ere*_*non 33 c++ gcc clang language-lawyer
给出以下代码:
#include <iostream>
struct Alice
{
template <typename A>
void operator|(const A& /*a*/) const
{
std::cout << "operator| member" << std::endl;
}
};
template <typename A>
void operator|(const A& /*a*/, const Alice& /*alice*/)
{
std::cout << "operator| non-member" << std::endl;
}
int main()
{
Alice a;
Alice b;
a | b;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它在没有警告的情况下编译GCC 4.8.1,4.9和clang 3.4,但给出了不同的结果.
$ g++ -Wall -Wextra -std=c++11 alice.cpp && ./a.out
operator| non-member
$ clang++ -Wall -Wextra -std=c++11 alice.cpp && ./a.out
operator| member
Run Code Online (Sandbox Code Playgroud)
是什么导致这种差异?我怎么能强迫同样的行为?
编辑:有趣的事实:const
从成员函数中删除限定符使得gcc更喜欢成员函数.但是,它并没有解决问题.
编辑: clang ++更喜欢非成员,如果-std=c++11
没有指定.
编辑: ICC 14.0更喜欢非会员,没有发出警告.
根据重载operator|
决策,有两个可行的函数:全局 - 模板的特化和推导的参数以及成员操作符函数模板的特化.两者都具有相同的签名 - 成员函数模板具有类型的隐式对象参数Alice const&
(参见§13.3.1/ 4).
因此,两个可行的函数(在模板参数推导之后)具有相同的签名.并且它们实例化的模板都不比另一个模板更专业.所以这确实是一种含糊不清,因此形成不良.令人惊讶的是,VC++是正确的.
我怎么能强迫同样的行为?
也许你应该删除歧义,Clang,VC++和GCC应该具有相同的行为.
归档时间: |
|
查看次数: |
737 次 |
最近记录: |