复制初始化和显式构造函数-编译器的差异



我发现Microsoft Visual C++编译器和gcc-4.8.1(由ideone.com提供)之间存在差异

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构造函数匹配,所以尝试过;但CCD_ 3不存在。好的

但我不知道MSVC++允许B b1 = s;是否正确,或者gcc拒绝它是否正确。MSVC++正在从A::A(const S&)构建一个临时,并用它通过B::B(const A&)初始化b1;我不知道为什么gcc会出错。

哪个编译器是对的?

(如后所述,如果我删除explicit,两个编译器都会拒绝B b1 = s;——可能是因为模板化构造函数现在对临时的隐式构造来说是公平的。)

编辑:从评论来看,MSVC++似乎也拒绝了Visual Studio 2012中的B b1 = s;行,所以一致认为这确实是一个错误。在哪种情况下,错误的性质是什么?错误消息是什么意思

从这个答案中窃取,标准说:

12.3转换[class.conv]

4最多一个用户定义的转换(构造函数或转换函数)隐式应用于单个值。

您正尝试在一个步骤中执行两个步骤,S需要转换为接受AB的构造函数,然后再转换另一个A的接受S的构造函数。解决方案是首先将S转换为A:

B b1 = static_cast<A>(s);

相关内容

最新更新