【问题标题】:Direct list initialization compiles successfully, but normal direct initialization fails, why?直接列表初始化编译成功,但是正常直接初始化失败,为什么?
【发布时间】:2015-09-09 02:22:00
【问题描述】:

例如这样的代码:

struct A { A(int); };
struct B { B(A);   };

int main()
{
    B b{{0}}; // OK
    B c({0}); // error
}

错误信息是:

f.cc: In function 'int main()':
f.cc:7:9: error: call of overloaded 'B(<brace-enclosed initializer list>)' is ambiguous
  B c({0}); // error

         ^
f.cc:7:9: note: candidates are:
f.cc:2:12: note: B::B(A)
 struct B { B(A);   };
        ^
f.cc:2:8: note: constexpr B::B(const B&)
 struct B { B(A);   };
        ^
f.cc:2:8: note: constexpr B::B(B&&)

【问题讨论】:

  • 是的,它应该是公开的。我已经改变了,谢谢!
  • 令人惊讶的是,即使我删除了 B 的复制和移动构造函数,这也会失败:coliru.stacked-crooked.com/a/7fb30cd9d5839ac2 编译错误消息相当莫名其妙,它与已删除的函数有歧义。
  • @ChrisBeck 删除的函数参与重载解析,因此删除它们没有任何区别并不令人困惑
  • B b({{{0}}});这编译,我不知道为什么。也许是巫毒教?
  • 我认为构造 {} 的大括号形式从不假定 initializer 列表,但括号版本 () 总是这样做,即使没有 initializer 列表 构造函数。这个答案提供了一些信息,但不是一个确定的答案。 stackoverflow.com/questions/29851502/…

标签: c++ initialization overload-resolution


【解决方案1】:

在最新的官方标准 C++14 中,您的第一次初始化是没有歧义的。 [over.match.list]:

由于不存在初始化列表构造函数,我们进入“第二阶段”。现在考虑 [over.best.ics]/4:

我们的元素是{0}。因此这不允许(用户定义的)转换{0} -> A 用于复制构造函数。显然,如果我们不在 [over.match.list] 的第二阶段,这并不适用,因此对于您的 B c({0}) 示例,c 不会发生列表初始化,并且会考虑两个构造函数。


CWG 问题 1467

第一个初始化当前与第二个初始化一样模棱两可。编译器还没有实现 CWG #1467 - 它的决议删除了上面引用的要点 (4.5)。
请参阅#2076,它选择还原更改:

issue 1467 的决议提出了一些似是而非的结构 格式不正确。例如,

struct A { A(int); };
struct B { B(A); };
B b{{0}};

这现在是模棱两可的,因为文本不允许用户定义 B 的复制和移动构造函数的转换已从 13.3.3.1 [over.best.ics] 第 4 段。

“文本”是前面提到的要点。 Richard Smith 提出以下措辞:

对于非类类型,我们允许从单项列表初始化 仅当列表中的元素本身不是 a 时才执行复制 列表(13.3.3.1.5 [over.ics.list] 项目符号 9.1)。 类似的规则 这种情况是在 13.3.3.1 [over.best.ics] 中添加回项目符号 第 4 段,但仅限于初始化程序本身是 初始化列表

        第二阶段 13.3.1.7 [over.match.list] 当初始化列表正好有一个         元素是 本身是一个初始化列表,其中目标是第一个参数 构造函数
X,转换为 到X 或参考(可能是 cv 合格的)X

由于初始化器 {0} 本身就是一个初始化器列表,因此该要点将使您的第一次初始化再次形成良好的格式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 2012-11-07
    • 2020-02-08
    • 1970-01-01
    • 2018-11-25
    相关资源
    最近更新 更多