【发布时间】:2015-12-07 12:37:21
【问题描述】:
我试图了解结合初始化列表和const auto 时 C++11 的正确行为应该是什么。对于以下代码,我在 GCC 和 Clang 之间得到了不同的行为,并且想知道哪个是正确的:
#include <iostream>
#include <typeinfo>
#include <vector>
int main()
{
const std::initializer_list<int> l1 = { 1, 2, 3 };
const auto l2 = { 1, 2, 3 };
std::cout << "explicit: " << typeid(l1).name() << std::endl;
std::cout << "auto: " << typeid(l2).name() << std::endl;
}
用g++编译的输出是:
explicit: St16initializer_listIiE
auto: St16initializer_listIKiE
虽然 clang++ 编译版本产生:
explicit: St16initializer_listIiE
auto: St16initializer_listIiE
似乎 GCC 正在将 auto 行转换为 std::initializer_list<const int> 而 Clang 生成 std::initializer_list<int>。当我使用 GCC 版本初始化 std::vector 时,它会产生问题。因此,以下在 Clang 下有效,但会为 GCC 产生编译器错误。
// Compiles under clang but fails for GCC because l4
std::vector<int> v2 { l2 };
如果 GCC 正在生成正确的版本,那么似乎建议应该扩展各种 STL 容器以包含针对这些情况的另一个列表初始化程序重载。
注意:这种行为在 GCC(4.8、4.9、5.2)和 Clang(3.4 和 3.6)的多个版本中似乎是一致的。
【问题讨论】:
-
你能检查
std::vector<int> v2 ( l2.begin(), l2.end() );(它应该可以工作)考虑到这一点,也许应该接受任何类型的隐式转换的初始化列表,即使推导发生了变化。另一方面,这可能会导致初始化列表构造函数更频繁地隐藏其他构造函数。 -
是`std::vector
v2 (l2.begin(), l2.end());确实有效。