【发布时间】:2014-01-09 10:31:33
【问题描述】:
我发现 Microsoft Visual C++ 编译器与 gcc-4.8.1(由 ideone.com 提供)之间存在差异。考虑以下 SSCCE:
struct S
{
int x;
};
class A
{
public:
int x;
A(const S& s) : x(s.x) {}
};
class B
{
int x, y;
public:
template <typename T> explicit B(const T& t) : x(t.x), y(t.y) {}
B(const A& a) : x(a.x), y(0) {}
};
int main() {
S s = {1};
B b1 = s; // Compiles OK on MSVC++;
// Fails on gcc - conversion from ‘S’ to non-scalar type ‘B’ requested
B b2(s); // Fails on both - Error: y is not a member of S in B::B<S>(const T &)
}
我理解为什么 B b2(s); 行失败 - explicit 构造函数匹配,所以它被尝试了;但t.y 不存在。很好。
但我无法确定 MSVC++ 是否正确允许B b1 = s;,或者 gcc 是否正确拒绝它。 MSVC++ 正在从A::A(const S&) 构造一个临时对象,并使用它通过B::B(const A&) 初始化b1;我不确定为什么 gcc 错误。
哪个编译器是对的?
(作为后记,如果我删除 explicit 两个编译器都拒绝 B b1 = s; - 大概是因为模板化的构造函数现在对于临时的隐式构造来说是公平的游戏。)
编辑: 从 cmets 看来,MSVC++ 似乎也拒绝了 Visual Studio 2012 中的 B b1 = s; 行,因此大家一致认为这确实是一个错误。在这种情况下 - 错误的性质是什么?那条错误消息是什么意思?
【问题讨论】:
-
VS2012 也因
B b1 = s;而失败。我相信失败是正确的行动。哪个 VS 没有失败? -
有趣。我的版本是 VS2010,所以它可能是一个固定的错误(升级时可能会破坏我们的代码!)。不过,我仍然很想知道发生了什么。
-
@egur - 2012 年的错误信息是什么?
-
这是一个错误,因为从 S 构造 B 需要连续两次用户定义的转换 (S -> A -> B),而只允许一次。 VS2010 可能允许它。
-
@Simple 我发布了一个答案,如果我对任何细节有误,请随时纠正我。
标签: c++ visual-c++ gcc constructor