std::tuple<Types...>:: tuple
|
定义于头文件
<tuple>
|
||
|
constexpr
tuple
(
)
;
|
(1) |
(C++11 起)
(条件性显式) |
|
tuple
(
const
Types
&
...
args
)
;
|
(2) |
(自 C++11 起)
(自 C++14 起为 constexpr) (条件性 explicit) |
|
template
<
class
...
UTypes
>
tuple ( UTypes && ... args ) ; |
(3) |
(自 C++11 起)
(自 C++14 起为 constexpr) (条件性显式) |
|
template
<
class
...
UTypes
>
constexpr tuple ( tuple < UTypes... > & other ) ; |
(4) |
(C++23 起)
(条件性显式) |
|
template
<
class
...
UTypes
>
tuple ( const tuple < UTypes... > & other ) ; |
(5) |
(自 C++11 起)
(自 C++14 起为 constexpr) (条件性显式) |
|
template
<
class
...
UTypes
>
tuple ( tuple < UTypes... > && other ) ; |
(6) |
(自 C++11 起)
(自 C++14 起为 constexpr) (条件性显式) |
|
template
<
class
...
UTypes
>
constexpr tuple ( const tuple < UTypes... > && other ) ; |
(7) |
(C++23 起)
(条件性显式) |
|
template
<
class
U1,
class
U2
>
constexpr tuple ( std:: pair < U1, U2 > & p ) ; |
(8) |
(C++23 起)
(条件性显式) |
|
template
<
class
U1,
class
U2
>
tuple ( const std:: pair < U1, U2 > & p ) ; |
(9) |
(C++11 起)
(C++14 起为 constexpr) (条件性 explicit) |
|
template
<
class
U1,
class
U2
>
tuple ( std:: pair < U1, U2 > && p ) ; |
(10) |
(自 C++11 起)
(自 C++14 起为 constexpr) (条件性 explicit) |
|
template
<
class
U1,
class
U2
>
constexpr tuple ( const std:: pair < U1, U2 > && p ) ; |
(11) |
(C++23 起)
(条件性显式) |
|
template
<
tuple-like UTuple
>
constexpr tuple ( UTuple && u ) ; |
(12) |
(C++23 起)
(条件性显式) |
|
tuple
(
const
tuple
&
other
)
=
default
;
|
(13) | (C++11 起) |
|
tuple
(
tuple
&&
other
)
=
default
;
|
(14) | (自 C++11 起) |
|
分配器扩展构造函数
|
||
|
template
<
class
Alloc
>
tuple ( std:: allocator_arg_t , const Alloc & a ) ; |
(15) |
(C++11 起)
(C++20 起为 constexpr) (条件性 explicit) |
|
template
<
class
Alloc
>
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(16) |
(自 C++11 起)
(自 C++20 起为 constexpr) (条件性 explicit) |
|
template
<
class
Alloc,
class
...
UTypes
>
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(17) |
(自 C++11 起)
(自 C++20 起为 constexpr) (条件性 explicit) |
|
template
<
class
Alloc,
class
...
UTypes
>
constexpr
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(18) |
(C++23 起)
(条件性显式) |
|
template
<
class
Alloc,
class
...
UTypes
>
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(19) |
(自 C++11 起)
(自 C++20 起为 constexpr) (条件性 explicit) |
|
template
<
class
Alloc,
class
...
UTypes
>
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(20) |
(自 C++11 起)
(自 C++20 起为 constexpr) (条件性 explicit) |
|
template
<
class
Alloc,
class
...
UTypes
>
constexpr
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(21) |
(自 C++23 起)
(条件性显式) |
|
template
<
class
Alloc,
class
U1,
class
U2
>
constexpr
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(22) |
(自 C++23 起)
(条件性显式) |
|
template
<
class
Alloc,
class
U1,
class
U2
>
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(23) |
(自 C++11 起)
(自 C++20 起为 constexpr) (条件性 explicit) |
|
template
<
class
Alloc,
class
U1,
class
U2
>
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(24) |
(自 C++11 起)
(自 C++20 起为 constexpr) (条件性 explicit) |
|
template
<
class
Alloc,
class
U1,
class
U2
>
constexpr
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(25) |
(自 C++23 起)
(条件性显式) |
|
template
<
class
Alloc, tuple
-
like UTuple
>
constexpr tuple ( std:: allocator_arg_t , const Alloc & a, UTuple && u ) ; |
(26) |
(C++23 起)
(条件性显式) |
|
template
<
class
Alloc
>
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(27) |
(C++11 起)
(C++20 起为 constexpr) |
|
template
<
class
Alloc
>
tuple
(
std::
allocator_arg_t
,
const
Alloc
&
a,
|
(28) |
(C++11 起)
(C++20 起为 constexpr) |
构造一个新的元组。
在以下描述中,令
-
i
按顺序处于范围
[ 0 ,sizeof... ( Types ))内, -
Ti为Types中的第i个类型,且 -
Ui为名为UTypes的模板参数包中的第i个类型,
其中索引从零开始。
- 此重载仅当对所有 i , std:: is_default_constructible < Ti > :: value 为 true 时参与重载决议。
-
当且仅当至少存在一个
i
使得
Ti无法从 { } 进行复制列表初始化时,该构造函数为 explicit 。
- 此重载仅在满足以下条件时参与重载决议: sizeof... ( Types ) >= 1 且对于所有 i , std:: is_copy_constructible < Ti > :: value 为 true 。
- 当且仅当存在至少一个 i 使得 std:: is_convertible < const Ti & , Ti > :: value 为 false 时,此构造函数为 explicit 。
-
此重载仅在满足以下所有条件时参与重载决议:
- sizeof... ( Types ) == sizeof... ( UTypes ) ,
- sizeof... ( Types ) >= 1 ,
- std:: is_constructible < Ti, Ui > :: value 对所有 i 均为 true ,且
-
令
D为 std:: decay < U0 > :: type (C++20 前) std:: remove_cvref_t < U0 > (C++20 起) ,-
若
sizeof...
(
Types
)
==
1
,则
D不能是std::tuple,否则 -
若
sizeof...
(
Types
)
==
2
或
sizeof...
(
Types
)
==
3
,则
D不能是 std::allocator_arg_t ,或T0必须是 std::allocator_arg_t 。
-
若
sizeof...
(
Types
)
==
1
,则
- 当且仅当至少存在一个 i 使得 std:: is_convertible < Ui, Ti > :: value 为 false 时,该构造函数为 explicit 。
|
(C++23 起) |
形式化地,令
FWD
(
other
)
为
std::
forward
<
decltype
(
other
)
>
(
other
)
,对于所有
i
,使用
std
::
get
<
i
>
(
FWD
(
other
)
)
初始化元组的第
i
个元素。
-
此重载仅在满足以下所有条件时参与重载决议:
- sizeof... ( Types ) == sizeof... ( UTypes ) ,
- 对所有 i , std:: is_constructible_v < Ti, decltype ( std :: get < i > ( FWD ( other ) ) ) > 为 true ,且
-
满足以下任一条件:
- sizeof... ( Types ) 不等于 1 ,或
-
(当
Types...展开为T且UTypes...展开为U时) std:: is_convertible_v < decltype ( other ) , T > 、 std:: is_constructible_v < T, decltype ( other ) > 和 std:: is_same_v < T, U > 均为 false 。
- 当且仅当对至少一个 i , std:: is_convertible_v < decltype ( std :: get < i > ( FWD ( other ) ) ) , Ti > 为 false 时,这些构造函数为 explicit 。
|
(since C++23) |
形式化地,令 FWD ( p ) 为 std:: forward < decltype ( p ) > ( p ) ,使用 std :: get < 0 > ( FWD ( p ) ) 初始化第一个元素,并使用 std :: get < 1 > ( FWD ( p ) ) 初始化第二个元素。
-
此重载仅在以下条件满足时参与重载决议:
- sizeof... ( Types ) == 2 ,
- std:: is_constructible_v < T0, decltype ( std :: get < 0 > ( FWD ( p ) ) ) > 为 true ,且
- std:: is_constructible_v < T1, decltype ( std :: get < 1 > ( FWD ( p ) ) ) > 为 true 。
- 当且仅当 std:: is_convertible_v < decltype ( std :: get < 0 > ( FWD ( p ) ) ) , T0 > 或 std:: is_convertible_v < decltype ( std :: get < 1 > ( FWD ( p ) ) ) , T1 > 为 false 时,该构造函数为 explicit 。
|
(自 C++23 起) |
tuple-like
构造函数。构造一个元组,其中每个元素从
u
的对应元素构造。
形式上,对于所有
i
,用
std
::
get
<
i
>
(
std::
forward
<
UTuple
>
(
u
)
)
初始化元组的第
i
个元素。
-
此重载仅在满足以下所有条件时参与重载决议:
- std:: same_as < std:: remove_cvref_t < UTuple > , std:: tuple > 为 false ,
- std:: remove_cvref_t < UTuple > 不是 std::ranges::subrange 的特化,
- sizeof... ( Types ) 等于 std:: tuple_size_v < std:: remove_cvref_t < UTuple >> ,
- std:: is_constructible_v < Ti, decltype ( std :: get < i > ( std:: forward < UTuple > ( u ) ) ) > 对所有的 i 均为 true ,且
-
满足以下任一条件:
- sizeof... ( Types ) 不等于 1 ,或
-
(当
Types...展开为T时) std:: is_convertible_v < UTuple, T > 与 std:: is_constructible_v < T, UTuple > 均为 false 。
- 如果任何引用元素的初始化会将其绑定到临时对象,则此构造函数被定义为已删除。
- 此构造函数在它执行的每个操作都是 constexpr 时为 constexpr 。对于空元组 std:: tuple <> ,它是 constexpr 。
- std:: is_copy_constructible < Ti > :: value 必须对所有 i 为 true ,否则 行为未定义 (C++20 前) 程序非良构 (C++20 起) 。
i
个元素。
- 此构造函数是 constexpr 的,当且仅当其执行的每个操作都是 constexpr 的。对于空元组 std:: tuple <> ,该构造函数是 constexpr 的。
- std:: is_move_constructible < Ti > :: value 必须对全部 i 为 true ,否则 行为未定义 (C++20 前) 此重载不参与重载决议 (C++20 起) 。
目录 |
参数
| args | - | 用于初始化元组各元素的值 |
| other | - | 用于初始化元组各元素的值元组 |
| p | - | 用于初始化二元组两个元素的数值对 |
| u | - |
用于初始化元组各元素的
tuple-like
对象值
|
| a | - | 用于分配器构造的分配器 |
注释
条件显式构造函数使得在复制初始化上下文中使用列表初始化语法构造元组成为可能:
std::tuple<int, int> foo_tuple() { // return {1, -1}; // N4387 之前的错误用法 return std::make_tuple(1, -1); // 始终有效 }
请注意,如果列表中的某些元素无法隐式转换为目标元组的对应元素,则构造函数将变为显式:
using namespace std::chrono; void launch_rocket_at(std::tuple<hours, minutes, seconds>); launch_rocket_at({hours(1), minutes(2), seconds(3)}); // 正确 launch_rocket_at({1, 2, 3}); // 错误:int 不能隐式转换为 duration 类型 launch_rocket_at(std::tuple<hours, minutes, seconds>{1, 2, 3}); // 正确
示例
#include <iomanip> #include <iostream> #include <memory> #include <string> #include <string_view> #include <tuple> #include <type_traits> #include <vector> // 辅助函数,用于将向量打印到流 template<class Os, class T> Os& operator<<(Os& os, std::vector<T> const& v) { os << '{'; for (auto i{v.size()}; const T& e : v) os << e << (--i ? "," : ""); return os << '}'; } template<class T> void print_single(T const& v) { if constexpr (std::is_same_v<T, std::decay_t<std::string>>) std::cout << std::quoted(v); else if constexpr (std::is_same_v<std::decay_t<T>, char>) std::cout << "'" << v << "'"; else std::cout << v; } // 用于打印任意大小元组的辅助函数 template<class Tuple, std::size_t N> struct TuplePrinter { static void print(const Tuple& t) { TuplePrinter<Tuple, N - 1>::print(t); std::cout << ", "; print_single(std::get<N - 1>(t)); } }; template<class Tuple> struct TuplePrinter<Tuple, 1> { static void print(const Tuple& t) { print_single(std::get<0>(t)); } }; template<class... Args> void print(std::string_view message, const std::tuple<Args...>& t) { std::cout << message << " ("; TuplePrinter<decltype(t), sizeof...(Args)>::print(t); std::cout << ")\n"; } // 结束辅助函数 int main() { std::tuple<int, std::string, double> t1; print("值初始化,t1:", t1); std::tuple<int, std::string, double> t2{42, "测试", -3.14}; print("使用值初始化,t2:", t2); std::tuple<char, std::string, int> t3{t2}; print("隐式转换,t3:", t3); std::tuple<int, double> t4{std::make_pair(42, 3.14)}; print("由一对构造,t4:", t4); // 给定分配器 my_alloc 具有单参数构造函数 // my_alloc(int); 使用 my_alloc(1) 在 vector 中分配 5 个 int using my_alloc = std::allocator<int>; std::vector<int, my_alloc> v{5, 1, my_alloc{/* 1 */}}; // 使用 my_alloc(2) 在元组中的向量内分配 5 个整型 std::tuple<int, std::vector<int, my_alloc>, double> t5 {std::allocator_arg, my_alloc{/* 2 */}, 42, v, -3.14}; print("使用分配器构造,t5:", t5); }
可能的输出:
值初始化,t1: (0, "", 0)
使用值初始化,t2: (42, "Test", -3.14)
隐式转换,t3: ('*', "Test", -3)
从 pair 构造,t4: (42, 3.14)
使用分配器构造,t5: (42, {1,1,1,1,1}, -3.14)
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 适用版本 | 发布时行为 | 正确行为 |
|---|---|---|---|
| LWG 2510 | C++11 | 默认构造函数为隐式 | 改为条件性显式 |
| LWG 3121 | C++11 |
单元素元组构造函数可能递归检查约束;
allocator_arg_t
参数引发歧义
|
进一步约束构造函数 |
| LWG 3158 | C++11 | 对应默认构造函数的分配器使用构造函数为隐式 | 改为条件性显式 |
| LWG 3211 | C++11 |
tuple<>
的默认构造函数是否为平凡未作规定
|
要求必须为平凡 |
| LWG 4045 | C++23 |
类元组
构造函数可能产生悬垂引用
|
定义为已删除 |
| N4387 | C++11 | 部分构造函数为显式,阻碍了有用行为 | 多数构造函数改为条件性显式 |
另请参阅
将一个
tuple
的内容赋值给另一个
(公开成员函数) |
|
|
(C++11)
|
创建由参数类型定义的
tuple
对象
(函数模板) |
|
(C++11)
|
创建左值引用组成的
tuple
或将 tuple 解包为独立对象
(函数模板) |
|
(C++11)
|
创建
转发引用
组成的
tuple
(函数模板) |
构造新的
pair
(
std::pair<T1,T2>
的公开成员函数)
|