为什么= {}初始化对元组不起作用?

Deq*_*ing 25 c++ tuples initializer-list c++11 list-initialization

对我而言,a pair只是a的特例tuple,但令我惊讶的是:

pair<int, int> p1(1, 2);   // ok
tuple<int, int> t1(1, 2);  // ok

pair<int, int> p2={1, 2};  // ok
tuple<int, int> t2={1, 2}; // compile error
Run Code Online (Sandbox Code Playgroud)

我们{}用来初始化时为什么会有区别tuple

我试过甚至g++ -std=c++1y但仍然有错误:

a.cc: In function 'int main()':
a.cc:9:29: error: converting to 'std::tuple<int, int>' from initializer list would use explicit constructor 'constexpr std::tuple<_T1, _T2>::tuple(_U1&&, _U2&&) [with _U1 = int; _U2 = int; <template-parameter-2-3> = void; _T1 = int; _T2 = int]'
     tuple<int, int> t2={1, 2};
                             ^
Run Code Online (Sandbox Code Playgroud)

How*_*ant 26

除了Praetorian的 正确答案(我已经投票),我想添加更多信息......

在Post-C++ 14之后,该标准已经改为允许:

tuple<int, int> t2={1, 2}; 
Run Code Online (Sandbox Code Playgroud)

编译并具有预期的语义.这样做的提议是N4387.这也将允许构造如:

tuple<int, int>
foo()
{
    return {1, 2};
}
Run Code Online (Sandbox Code Playgroud)

只有Ttuple所有参数中都可以隐式地构造它时才允许它.

作为不符合的扩展,libc ++已经实现了这种行为.

  • @MattMcNabb:是的.`is_convertible <int,std :: tuple <int >> {}`在C++ 14中为false,在C++ 1z中为true.C++内省的力量已经变得如此强大,以至于现在几乎不可能编写符合标准的扩展. (9认同)

Pra*_*ian 24

您尝试调用的tuple构造函数explicit,因此复制列表初始化将失败.相应的pair构造函数不是explicit.

将您的代码更改为

tuple<int, int> t2{1, 2};
Run Code Online (Sandbox Code Playgroud)

它会编译.

  • 有没有理由`tuple`使用显式构造函数? (3认同)
  • @Deqing如果没有,则可以从可转换为该类型的值隐式构造包含单个类型的`tuple`. (2认同)
  • @Praetorian为了避免这种情况,或许元组可能有明确的构造函数接受一个参数,而非显式构造函数需要两个或更多? (2认同)