为什么 `initializer_list<pair>` 和 `initializer_list<tuple>` 表现不同?
Why do `initializer_list<pair>` and `initializer_list<tuple>` behave differently?
以下代码编译运行:
#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<pair>
的参数(有效),而另一个使用 initializer_list<tuple>
(无效)。然而,cplusplus.com states that
Pairs are a particular case of tuple.
那么为什么一个代码有效而另一个无效?
附加信息
第二种情况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} } } );
^
cplusplus.com 不是一个很好的网站,因为它充斥着像 "Pairs are a particular case of tuple." 这样的虚假陈述。您可以改用 cppreference
。事实上 pair 不是 tuple 的特例。
现在认为tuple
是比较好的设计; pair
比较老,现在不能更改,因为向后兼容。
错误消息表明不同之处在于 tuple
有一个 explicit
构造函数,而 pair
没有。
这意味着您需要在构造元组时提及class名称:
ext( { std::tuple<double,std::vector<double>>{1.0, {2.0, 3.0, 4.0} } } );
这将在 C++17 中更改:tuple
的构造函数将是显式的,当且仅当元组的类型之一是具有显式构造函数的 class 类型时。 gcc 6 已经实现了这个特性。 (信用——Jonathan Wakely)。参见 N4387
以下代码编译运行:
#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<pair>
的参数(有效),而另一个使用 initializer_list<tuple>
(无效)。然而,cplusplus.com states that
Pairs are a particular case of tuple.
那么为什么一个代码有效而另一个无效?
附加信息
第二种情况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} } } );
^
cplusplus.com 不是一个很好的网站,因为它充斥着像 "Pairs are a particular case of tuple." 这样的虚假陈述。您可以改用 cppreference
。事实上 pair 不是 tuple 的特例。
现在认为tuple
是比较好的设计; pair
比较老,现在不能更改,因为向后兼容。
错误消息表明不同之处在于 tuple
有一个 explicit
构造函数,而 pair
没有。
这意味着您需要在构造元组时提及class名称:
ext( { std::tuple<double,std::vector<double>>{1.0, {2.0, 3.0, 4.0} } } );
这将在 C++17 中更改:tuple
的构造函数将是显式的,当且仅当元组的类型之一是具有显式构造函数的 class 类型时。 gcc 6 已经实现了这个特性。 (信用——Jonathan Wakely)。参见 N4387