我从
http://en.cppreference.com/w/cpp/language/function_template#Function_template_overloading以下的例子
和俚语(3.4)似乎正在处理它,而g(4.8.3)给出了一个“模糊的重载”错误:
和俚语(3.4)似乎正在处理它,而g(4.8.3)给出了一个“模糊的重载”错误:
struct A {}; template<class T> struct B { template<class R> void operator*(R&){ cout << "1" << endl; } // #1 }; template<class T,class R> void operator*(T&,R&) { cout << "2" << endl;} // #2 int main() { A a; B<A> b; b * a; //prints 1 }
cl声正确地打印1(根据cppreference的预期),而g给出这个错误:
test_templates.cpp: In function ‘int main()’: test_templates.cpp:13:5: error: ambiguous overload for ‘operator*’ (operand types are ‘B<A>’ and ‘A’) b * a; //prints 1 ^ test_templates.cpp:13:5: note: candidates are: test_templates.cpp:7:26: note: void B<T>::operator*(R&) [with R = A; T = A] template<class R> void operator*(R&){ cout << "1" << endl; } // #1 ^ test_templates.cpp:9:33: note: void operator*(T&,R&) [with T = B<A>; R = A] template<class T,R&) { cout << "2" << endl;} // #2
实际上这是不正常的吗?
解决方法
这个例子取自
standard(这是c 11的草案).
14.5.6.2功能模板的部分排序第3段示例:
struct A { }; template<class T> struct B { template<class R> int operator*(R&); // #1 }; template<class T,class R> int operator*(T&,R&); // #2 // The declaration of B::operator* is transformed into the equivalent of // template<class R> int operator*(B<A>&,R&); // #1a int main() { A a; B<A> b; b * a; // calls #1a }
所以,这个标准本身就说这是合法的代码.我可以复制粘贴规则,但也可以点击链接并跳转到相关的位置.我的观点只是为了证明这是标准定义的正确的可编译代码.
对于我的debian cl ang 3.5.0编译它是值得的,cl ang 3.4.2必须执行-std = c 11,g 4.9.1报告模糊在所有情况下(我甚至尝试了1y).
不过,我很笨拙的行为感到困惑.我以为在早期版本的c中可能是含糊的,消除歧义的规则被添加为c11的一部分,而g没有跟上.但是cl ang 3.5甚至用-std = c 98编译.