ISO C++以下代码的标准一致结果
#include <iostream>
template< typename U >
struct base {
template< typename T >
base const & operator<<( T x ) const {
std::cout << sizeof( x ) << std::flush;
return *this;
}
};
template< typename U >
struct derived : public base< U > {
using base<U>::operator<<;
derived const & operator<<( float const & x ) const {
std::cout << "derived" << std::flush;
return *this;
}
};
int main() {
unsigned char c( 3 );
derived< double > d;
d << c;
d.operator<<( c );
return 0;
}
您能否解释一下获得上述代码的正确答案所涉及的规则(与模板、积分提升等相关的重载和覆盖)?有效吗?如果规则太长,请提供文献参考。最新的编译器对于正确的结果存在不同意见。 gcc-4.6 和 icpc-12.1.0 声称“11”是正确答案,但 VS2010 拒绝编译 d << c;
由于不明确,但接受 d.operator<<( c );
。后者输出 1
iirc。那么谁是对的,谁是错的呢?
#include <iostream>
template< typename U >
struct base {
template< typename T >
base const & operator<<( T x ) const {
std::cout << sizeof( x ) << std::flush;
return *this;
}
};
template< typename U >
struct derived : public base< U > {
using base<U>::operator<<;
derived const & operator<<( float const & x ) const {
std::cout << "derived" << std::flush;
return *this;
}
};
int main() {
unsigned char c( 3 );
derived< double > d;
d << c;
d.operator<<( c );
return 0;
}
Can you please explain the rules involved to obtain a correct answer of the above code (overloading and overriding in connection with templates, integral promotion, ...)? Is it valid? If the rules are too lengthy please provide literature pointers. The latest compilers disagree about the correct result. gcc-4.6 and icpc-12.1.0 claim "11" is the correct answer but VS2010 refuses to compile d << c;
due to ambiguities but accepts d.operator<<( c );
. The latter outputs 1
iirc. So who's right and who's wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
“11”是正确的输出。
对于这两个表达式,派生运算符<<都是和基运算符<<是候选人。然后根据候选者所需的隐式转换序列对候选者进行比较。因为基运算符<<是一个模板函数,其中类型 T 已被推导为与参数匹配,在这两种情况下它都是更好的匹配。
确切的规则相当长。您可以在当前 C++ 草案标准 n3337 的第 13.3 节重载解决中找到详细信息,链接到 此工作组论文列表。
如果您问为什么 MSVC 不编译一条语句,我不太确定,但是当存在多个彼此不更好的计算 ICS 时,函数调用是不明确的(如 13.3.3 中定义)。在
d << 的情况下,MSVC 似乎为至少一个重载计算了错误的 ICS。 c
,但诊断没有提供更多详细信息:"11" is the correct output.
For both expressions both the derived operator<< and base operator<< are candidates. Then the candidates are compared based on the implicit conversion sequences they require. Because the base operator<< is a template function where the type T has been deduced to match the argument it comes up as the better match in both cases.
The exact rules are pretty long. You can find the details in section 13.3 Overload resolution of the current C++ draft standard, n3337 linked to in this list of the working group's papers.
If you're asking why MSVC doesn't compile the one statement, I'm not exactly sure, but a function call is ambiguous when there are multiple computed ICSs that are not better than each other (as defined in 13.3.3). MSVC seems to be computing the wrong ICS for at least one of the overloads in the case of
d << c
, but the diagnostic doesn't give any more details:它不会编译,因为您要求自动调用
operator <<
。这就像有运算符+
,以及可以转换为基本类型(例如,int
)的转换运算符。例如:并像这样使用它:
这里
operator +
不能被隐式调用,因为operator int
也是可能的。如果传递,int
,但是,operator +(int)
将被调用。要使用double
调用operator+,我们可以这样做:我不知道编译器规则和严格的标准定义。
我还发现,如果我们将基类和派生类更改为非模板类,问题仍然存在(在 VC10/11 中):
It doesn't compile because you are asking
operator <<
to be invoked automatically. It is like havingoperator +
, as well as having conversion operator that can convert to basic type (say, toint
). For example:And using it like:
Here
operator +
cannot be implicitly invoked, sinceoperator int
is also possible. If you pass,int
, however,operator +(int)
will be called. To invoke operator+ withdouble
, we can do:I don't know about the compiler rules, and the strict standards definition.
I also found out, that if we change the
base
andderived
classes as non-template classes, the problem would still remain (in VC10/11):