【发布时间】:2013-11-13 14:11:49
【问题描述】:
在尝试 clang-3.4(从 git 编译)时,它未能编译我的一个项目,抱怨在解决重载运算符时存在歧义。 我发现有两个模板化的运算符,一个被声明为成员函数,另一个被声明为非成员函数,两者看起来都非常匹配。
以下SSCCE演示情况:
#include <iostream>
struct ostr {
std::ostream& s;
template<class T>
ostr& operator<<(const T& x) { s << x; return *this; }
};
struct xy {
double x, y;
};
template<class Stream>
Stream& operator<<(Stream& s, const xy& x) {
s << "[" << x.x << ", " << x.y << "]";
return s;
}
int main() {
ostr os{std::cout};
xy x{4, 5};
os << "Value is: " << x <<"\n";
}
该项目之前编译得很好,我用几个编译器(gcc 4.5、4.6、4.7、4.8 和 clang 3.3)再次检查了这个 SSCCE,所有编译器都在没有任何警告的情况下编译它(使用 @ 987654329@)。所有编译器都设置为 C++11/C++0x 标准。
将ctor添加到ostr后,即使在MSVC 2012和2010上也能正常编译)
将operator<<s 都设为非成员会在所有编译器中表现出歧义(正如预期的那样)
查看标准草案(N3242 和 N3690)后,我没有找到任何使成员函数/运算符比非成员函数/运算符更匹配的东西。
所以我没能证明clang-3.4 是错的,我想知道谁是对的。
因此我的问题是:
- 此代码有效吗?成员运算符/函数是否应该比非成员运算符/函数更好地匹配,这是 clang-3.4 中的一个错误?
- 还是所有其他编译器都错误/过于宽松?
我知道将第二个 operator<< 更改为非模板函数(使用 std::ostream 而不是模板参数)将解决歧义并按预期工作,但这不是重点。 em>
【问题讨论】:
-
+1 因为这是一个有趣的问题;但如果可以的话,我会再次 +1,以确保您的清晰和彻底!
-
“成员运算符/函数是否应该比非成员运算符/函数更好匹配” 不,但它们作为附加参数获得对其类类型的引用,只是为了解决重载问题。
-
可能与this clang bug相关
-
DyP:这个错误应该在 r190470 中得到修复。我用当前版本(r194576,一小时前提交)对其进行了测试,结果仍然相同。
-
尝试使用 before r190470 版本,例如 coliru 使用的 184460:它的行为与其他编译器一样。