【问题标题】:Why do `initializer_list<pair>` and `initializer_list<tuple>` behave differently?为什么 `initializer_list<pair>` 和 `initializer_list<tuple>` 行为不同?
【发布时间】:2016-07-28 08:47:55
【问题描述】:

以下代码编译并运行:

#include <initializer_list>
#include <iostream>
#include <vector>
#include <tuple>

void ext( std::initializer_list<std::pair<double, std::vector<double> >> myList )
{
    //Do something
}

///////////////////////////////////////////////////////////

int main(void) {
    ext( { {1.0, {2.0, 3.0, 4.0} } } );
    return 0;
}

虽然这个没有:

#include <initializer_list>
#include <iostream>
#include <vector>
#include <tuple>

void ext( std::initializer_list<std::tuple<double, std::vector<double> >> myList )
{
    //Do something
}

///////////////////////////////////////////////////////////

int main(void) {
    ext( { {1.0, {2.0, 3.0, 4.0} } } );
    return 0;
}

唯一的区别是,在第一种情况下,ext() 函数采用 initializer_list&lt;pair&gt; 类型的参数(有效),而其他使用 initializer_list&lt;tuple&gt;(无效)。但是,cplusplus.com states that

对是元组的一种特殊情况。

那么为什么一个代码有效而另一个无效?


其他信息

clang++在第二种情况下输出的错误是:

main.cpp:33:2: error: no matching function for call to 'ext'
      ext( { {1.0, {2.0, 3.0, 4.0} } } );
      ^~~
main.cpp:7:6: note: candidate function not viable: cannot convert initializer list argument to 'std::tuple<double,
      std::vector<double, std::allocator<double> > >'
void ext( std::initializer_list<std::tuple<double, std::vector<double> >> myList )
      ^
1 error generated.

当 g++ 输出时:

main.cpp: In function ‘int main()’:
main.cpp:33:35: error: converting to ‘std::tuple<double, std::vector<double, std::allocator<double> > >’ from initializer list would use explicit constructor ‘constexpr std::tuple<_T1, _T2>::tuple(const _T1&, const _T2&) [with _T1 = double; _T2 = std::vector<double>]’
  ext( { {1.0, {2.0, 3.0, 4.0} } } );
                                   ^

【问题讨论】:

    标签: c++ tuples initializer-list std-pair


    【解决方案1】:

    cplusplus.com 不是一个很好的网站,因为它充满了诸如“对是元组的特殊情况”之类的虚假陈述。您可以改用cppreference。事实上pair并不是元组的特例。

    现在认为tuple是更好的设计; pair 已经很老了,由于向后兼容,现在无法更改。

    错误信息表明区别在于tuple有一个explicit构造函数,而pair没有。

    这意味着在构造元组时需要提及类名:

     ext( { std::tuple<double,std::vector<double>>{1.0, {2.0, 3.0, 4.0} } } );
    

    这将在 C++17 中进行更改:当且仅当元组的类型之一是具有显式构造函数的类类型时,tuple 的构造函数才会是显式的。 gcc 6 已经实现了这个特性。 (信用 - 乔纳森维克利)。见N4387

    【讨论】:

    • 注:元组构造函数的explicit-ness 现在以参数类型为条件,并且示例代码在 C++17 中有效(今天使用 GCC 6 编译)。
    • @JonathanWakely 感谢您提供的信息。我只是想知道如果 OP 询问“为什么它很明确,这似乎很烦人”,我将如何回答,而我没有任何好的答案
    • @MM 感谢您的帮助!的确,这将是一个很好的问题……
    猜你喜欢
    • 2012-07-09
    • 2012-11-16
    • 2013-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 2016-04-29
    相关资源
    最近更新 更多