2016-08-13 50 views
1

如果看下面的代码,我认为main()中的两行应该调用initializer_list的构造函数InitSomething。正如我所料,gcc输出22,但是clang只输出一个2。铛是错的?Clang跳过初始化程序列表构造的处理

我在编译-std=c++14

#include <iostream> 

struct InitSomething { 
    explicit InitSomething(int) { std::cout << '1'; } 
    InitSomething(std::initializer_list<int>) { std::cout << '2'; } 
    operator int() { return 1; } 
}; 

int main() { 
    InitSomething init_something{1}; 
    InitSomething init_something_else{init_something}; 
} 

clang++ --version(我在Mac)的输出是

Apple LLVM version 7.3.0 (clang-703.0.31) 
Target: x86_64-apple-darwin15.5.0 
Thread model: posix 
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin 

g++ --version我提到的其他平台上的输出

g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4) 
Copyright (C) 2015 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+0

最近语言发生了变化,如果还有其他构造函数直接使用'some_value',则不会为**每个**集合{{some_value})支持initializer_list。 –

+0

@BoPersson你指的是C++ 17吗? – Curious

+1

我不确定它何时出现。寻找参考... –

回答

2

DR1467的标题关注总量,但作为第一个子弹的the wording it added to [dcl.init.list]/3不限于聚合茨:

如果T是一个类类型和初始化列表具有cv U类型,其中UT或从T派生的类,则 对象从该元素初始化的单一元件 (由复印通初始化 复制列表初始化,或通过直接初始化 直接列表初始化)。

然而,DR2137走到离这一措辞(用“聚合级”取代“的类类型”)背部等this bullet不再适用于非聚集体状InitSomething

相反,[dcl.init.list] /3.6适用,就像它预DR1467:

否则,如果T是一个类类型,构造函数被考虑。 枚举适用的构造函数,并通过重载分辨率([over.match], [over.match.list])选择最佳的构造函数 。

[over.match.list]并明确指出初始化列表构造是优选的,如果在所有可行的:

当非聚合类类型T的对象列表初始化这样 即[dcl.init.list ]指定重载解析是根据本节中的规则来执行 ,重载决策选择 构造在两个阶段:

  • 最初,候选函数是类T的初始化程序列表构造函数([dcl.init.list]),参数列表 包含作为单个参数的初始化程序列表。
  • 如果找不到可行的初始化程序列表构造函数,则重新执行重载解析,其中候选函数全部为 类T的构造函数,参数列表包含 初始化程序列表的元素。因为非初始化列表构造甚至没有候选人

所有这些谈论排名隐式转换序列无关。

Clang正在实施DR1467之后和DR2137之前的措辞。

+0

这种事情让我认真地问'initializer_list'是一个概念。 – Barry

相关问题