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

时间:2014-01-09 10:31:34

标签: c++ visual-c++ gcc constructor

我发现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&)的临时文件,并使用该文件通过b1初始化B::B(const A&);我不确定为什么会出现gcc错误。

哪个编译器正确?

(作为后注,如果我删除explicit两个编译器拒绝B b1 = s; - 大概是因为模板化的构造函数现在是隐式构造临时构建器的公平游戏。)

编辑:从评论中看来,MSVC ++似乎也拒绝了Visual Studio 2012中的B b1 = s;行,因此共识似乎确实是一个错误。在哪种情况下 - 错误的本质是什么?该错误消息意味着什么

1 个答案:

答案 0 :(得分:5)

answer被盗,标准说:

  

12.3转化[class.conv]

     

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

您尝试执行两个步骤S,需要转换为B的接受A的构造函数,然后转换为A接受S的构造函数。解决方案是首先将S投射到A

B b1 = static_cast<A>(s);