c++11 标准模板(STL)(std::tuple)(二)

本文详细介绍了C++标准库中的std::tuple类模板的构造函数,包括默认构造、直接构造、转换构造、转换复制构造、转换移动构造以及与pair的构造函数,以及它们的条件性和使用场景。
摘要由CSDN通过智能技术生成

 

定义于头文件 <tuple>

template< class... Types >
class tuple;

(C++11 起)

类模板 std::tuple 是固定大小的异类值汇集。它是 std::pair 的推广。

若 (std::is_trivially_destructible_v<Types> && ...) 为 true ,则 tuple 的析构函数是平凡的。

(C++17 起)

模板形参

Types...-tuple 所存储的元素的类型。支持空列表。

 

构造函数

std::tuple<Types...>::tuple

constexpr tuple();

(1)(C++11 起)
(条件性 explicit)

tuple( const Types&... args );

(2)(C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)

template< class... UTypes >
tuple( UTypes&&... args );

(3)(C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)

template< class... UTypes >
tuple( const tuple<UTypes...>& other );

(4)(C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)

template <class... UTypes>
tuple( tuple<UTypes...>&& other );

(5)(C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)

template< class U1, class U2 >
tuple( const pair<U1,U2>& p );

(6)(C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)

template< class U1, class U2 >
tuple( pair<U1,U2>&& p );

(7)(C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)

tuple( const tuple& other ) = default;

(8)(C++11 起)

tuple( tuple&& other ) = default;

(9)(C++11 起)

template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a );

(10)(C++11 起)
(C++20 起为 constexpr)
(条件性 explicit)
template< class Alloc >

tuple( std::allocator_arg_t, const Alloc& a,

       const Types&... args );
(11)(C++11 起)
(C++20 起为 constexpr)
(条件性 explicit)
template< class Alloc, class... UTypes >

tuple( std::allocator_arg_t, const Alloc& a,

       UTypes&&... args );
(12)(C++11 起)
(C++20 起为 constexpr)
(条件性 explicit)
template <class Alloc, class... UTypes>

tuple( std::allocator_arg_t, const Alloc& a,

       const tuple<UTypes...>& other );
(13)(C++11 起)
(C++20 起为 constexpr)
(条件性 explicit)
template< class Alloc, class... UTypes >

tuple( std::allocator_arg_t, const Alloc& a,

       tuple<UTypes...>&& other );
(14)(C++11 起)
(C++20 起为 constexpr)
(条件性 explicit)
template< class Alloc, class U1, class U2 >

tuple( std::allocator_arg_t, const Alloc& a,

       const pair<U1, U2>& p );
(15)(C++11 起)
(C++20 起为 constexpr)
(条件性 explicit)
template< class Alloc, class U1, class U2 >

tuple( std::allocator_arg_t, const Alloc& a,

       pair<U1, U2>&& p );
(16)(C++11 起)
(C++20 起为 constexpr)
(条件性 explicit)
template< class Alloc >

tuple( std::allocator_arg_t, const Alloc& a,

       const tuple& other );
(17)(C++11 起)
(C++20 起为 constexpr)
template< class Alloc >

tuple( std::allocator_arg_t, const Alloc& a,

       tuple&& other );
(18)(C++11 起)
(C++20 起为 constexpr)

 构造新的 tuple

1) 默认构造函数。值初始化所有元素。

此重载仅若 std::is_default_constructible<Ti>::value 对所有 i 为 true 才参与重载决议。

构造函数若且唯若对至少一个 iTi 不可从 {} 复制列表初始化才为 explicit 。

2) 直接构造函数。以对应参数初始化 tuple 的每个元素。

此重载仅若 sizeof...(Types) >= 1 与 std::is_copy_constructible<Ti>::value 对所有 i 为 true 才参与重载决议。

此构造函数若且唯若 std::is_convertible<const Ti&, Ti>::value 对至少一个 i 为 false 才为 explicit 。

3) 转换构造函数。以 std::forward<UTypes>(args) 中的对应值初始化 tuple 的每个元素。

此重载仅若 sizeof...(Types) == sizeof...(UTypes) 且 sizeof...(Types) >= 1 与 std::is_constructible<Ti, Ui&&>::value 对所有 i 为 true 才参与重载决议。

构造函数若且唯若才 std::is_convertible<Ui&&, Ti>::value 对至少一个 i 为 false 为 explicit 。

4) 转换复制构造函数。对 sizeof...(UTypes) 中所有 i ,以 std::get<i>(other) 初始化 tuple 的第 i 个元素。

此重载仅若

sizeof...(Types) == sizeof...(UTypes) 且
std::is_constructible_v<Ti, const Ui&> 对所有 i 为 true 且
sizeof...(Types) != 1 或

Types... 展开成 TUTypes... 展开成 U 时) std::is_convertible_v<const tuple<U>&, T> 、 std::is_constructible_v<T, const tuple<U>&> 与 std::is_same_v<T, U> 均为 false 才参与重载决议。

构造函数若且唯若 std::is_convertible<const Ui&, Ti>::value 对至少一个 i 为 false 才为 explicit 。

5) 转换移动构造函数。对 sizeof...(UTypes) 中所有 i ,以 std::forward<Ui>(std::get<i>(other)) 初始化 tuple 的第 i 个元素。

此重载仅若

sizeof...(Types) == sizeof...(UTypes) 且
std::is_constructible_v<Ti, Ui&&> 对所有 i 为 true 且
sizeof...(Types) != 1 或

Types... 展开成 TUTypes... 展开成 U 时) std::is_convertible_v<tuple<U>, T> 、 std::is_constructible_v<T, tuple<U>> 与 std::is_same_v<T, U> 均为 false 才参与重载决议。

构造函数若且唯若 std::is_convertible<Ui&&, Ti>::value 对至少一个 i 为 false 才为 explicit 。

6) pair 复制构造函数。构造 2-tuple ,从 p.first 构造第一个元素,从 p.second 构造第二个元素。

此重载仅若 sizeof...(Types) == 2 与 std::is_constructible<T0,const U1&>::value 与 std::is_constructible<T1, const U2&>::value 均为 true 才参与重载决议。

构造函数若且唯若 std::is_convertible<const U1&, T0>::value 或 std::is_convertible<const U2&, T1>::value 为 false 才为 explicit 。 }}

7) pair 移动构造函数。构造 2-tuple ,从 std::forward<U1>(p.first) 构造第一个元素,从 std::forward<U2>(p.second) 构造第二个元素。

此重载仅若 sizeof...(Types) == 2 与 std::is_constructible<T0, U1&&>::value 与 std::is_constructible<T1, U2&&>::value 均为 true 才参与重载决议。

构造函数若且唯若 std::is_convertible<U1&&, T0>::value 或 std::convertible<U2&&, T1>::value 为 false 才为 explicit 。

8) 隐式定义的复制构造函数。以 other 的对应元素初始化 tuple 的每个元素。

若此函数进行的每个操作都是 constexpr ,则它是 constexpr 。对于空 tuple std::tuple<> ,它是 constexpr 。

要求 std::is_copy_constructible<Ti>::value 对所有 i 为 true 。

9) 隐式定义的移动构造函数。以 std::forward<Ui>(std::get<i>(other)) 构造 tuple 的第 i 个元素。

若此函数进行的每个操作都是 constexpr ,则它是 constexpr 。对于空 tuple std::tuple<> ,它是 constexpr 。

要求 std::is_move_constructible<Ti>::value 对所有 i 为 true 。

10-18) 等同于 (1-9) ,除了以使用分配器构造创建每个元素每个元素,即以分配器 (Allocator) 对象 a 为额外参数传递给每个 std::uses_allocator<Ui, Alloc>::value 为 true 的对象的构造函数。

参数

args-用于初始化 tuple 每个元素的值
other-用于初始化 tuple 每个元素的值的 tuple
p-用于初始化此 2-tuple 的两个元素的值的 pair
a-用于使用分配器构造的分配器

 

注意

条件性 explicit 的构造函数使得可以用列表初始化语法于复制初始化语境构造 tuple :

std::tuple<int, int> foo_tuple() 
{
  return {1, -1};  // N4387 前错误
  return std::make_tuple(1, -1); // 始终工作
}

注意若列表中某元素不可隐式转换成目标 tuple 中的对应元素,则构造函数变为 explicit 。

using namespace std::chrono;
void launch_rocket_at(std::tuple<hours, minutes, seconds>);
 
launch_rocket_at({hours(1), minutes(2), seconds(3)}); // OK
launch_rocket_at({1, 2, 3}); // 错误: int 不可隐式转换成 duration
launch_rocket_at(std::tuple<hours, minutes, seconds>{1, 2, 3}); // OK

调用示例

#include <tuple>
#include <iostream>
#include <string>
#include <typeinfo>
#include <stdexcept>
#include <iostream>
#include <vector>
#include <memory>

// 打印任何大小 tuple 的辅助函数
template<class Tuple, std::size_t N>
struct TuplePrinter
{
    static void print(const Tuple& t)
    {
        TuplePrinter < Tuple, N - 1 >::print(t);
        std::cout << ", " << std::get < N - 1 > (t);
    }
};

template<class Tuple>
struct TuplePrinter<Tuple, 1>
{
    static void print(const Tuple& t)
    {
        std::cout << std::get<0>(t);
    }
};

template<class... Args>
void print(const std::tuple<Args...>& t)
{
    std::cout << "(";
    TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
    std::cout << ")" << std::endl;
}
// 辅助函数结束

int main()
{
    //1) 默认构造函数。值初始化所有元素。
    std::tuple<int, std::string, double> tuple1;
    std::cout << "Value-initialized: ";
    print(tuple1);

    //2) 直接构造函数。以对应参数初始化 tuple 的每个元素。
    std::tuple<int, std::string, double> tuple2(42, "Test", -3.14);
    std::cout << "Initialized with values: ";
    print(tuple2);

    //3) 转换构造函数。以 std::forward<UTypes>(args) 中的对应值初始化 tuple 的每个元素。
    std::tuple<char, std::string, int> tuple3(std::move(tuple2));
    std::cout << "Implicitly converted: ";
    print(tuple3);

    //4) 转换复制构造函数。对 sizeof...(UTypes) 中所有 i ,以 std::get<i>(other) 初始化 tuple 的第 i 个元素。
    std::tuple<char, std::string, int> tuple4(tuple2);
    std::cout << "Implicitly converted: ";
    print(tuple4);

    //5) 转换移动构造函数。对 sizeof...(UTypes) 中所有 i ,
    //以 std::forward<Ui>(std::get<i>(other)) 初始化 tuple 的第 i 个元素。
    std::tuple<char, std::string, int> tuple5(std::move(tuple2));
    std::cout << "Implicitly converted: ";
    print(tuple5);

    //6) pair 复制构造函数。构造 2-tuple ,从 p.first 构造第一个元素,从 p.second 构造第二个元素。
    std::tuple<int, double> tuple6(std::make_pair(42, 3.14));
    std::cout << "Constructed from a pair";
    print(tuple6);

    //7) pair 移动构造函数。构造 2-tuple ,从 std::forward<U1>(p.first) 构造第一个元素,
    //从 std::forward<U2>(p.second) 构造第二个元素。
    std::pair<int, double> pair1 = std::make_pair(42, 3.14);
    std::tuple<int, double> tuple7(std::move(pair1));
    std::cout << "Constructed from a pair";
    print(tuple7);

    //8) 隐式定义的复制构造函数。以 other 的对应元素初始化 tuple 的每个元素。
    std::tuple<char, std::string, int> tuple8(tuple2);
    std::cout << "Implicitly converted: ";
    print(tuple8);

    //9) 隐式定义的移动构造函数。以 std::forward<Ui>(std::get<i>(other)) 构造 tuple 的第 i 个元素。
    std::tuple<char, std::string, int> tuple9(std::move(tuple2));
    std::cout << "Implicitly converted: ";
    print(tuple9);

    return 0;
}

输出

Value-initialized: (0, , 0)
Initialized with values: (42, Test, -3.14)
Implicitly converted: (*, Test, -3)
Implicitly converted: (*, , -3)
Implicitly converted: (*, , -3)
Constructed from a pair(42, 3.14)
Constructed from a pair(42, 3.14)
Implicitly converted: (*, , -3)
Implicitly converted: (*, , -3)

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值