当前位置:   article > 正文

[C++] std::tuple

std::tuple

【C++】std::tuple

1、什么是tuple

​ std::tuple是C++11新标准引入的一个类模板,又称为元组,是一个固定大小的异构值集合,由std::pair泛化而来。pair可以看作是tuple的一种特殊情况,成员数目限定为两个。tuple可以有任意个成员数量,但是每个确定的tuple类型的成员数目是固定的。

​ 从概念上讲,它们类似于C的结构体,但是不具有命名的数据成员,我们也可以把他当做一个通用的结构体来用,不需要创建结构体又获取结构体的特征,在某些情况下可以取代结构体使程序更简洁,直观。

​ tuple 的应用场景很广泛,例如当需要存储多个不同类型的元素时,可以使用 tuple;当函数需要返回多个数据时,可以将这些数据存储在 tuple 中,函数只需返回一个 tuple 对象即可。

2、tuple的基本用法

①tuple对象的创建和初始化

tuple 本质上是一个以可变模板参数定义的类模板,它定义在 头文件并位于 std 命名空间中。因此要想使用 tuple 类模板,程序中需要首先引入以下代码:

#include <tuple>
  • 1

实例化 tuple 模板类对象常用的方法有两种,一种是借助该类的构造函数,另一种是借助 make_tuple() 函数。

1)类的构造函数
constexpr tuple(); 				//无参构造函数
tuple( const Types&... args ); 	//拷贝构造函数
tuple (tuple&& tpl);			//移动构造函数

/*隐式类型转换构造函数*/
template< class... UTypes >
	tuple(const tuple<UTypes...>& other );	//左值方式
template< class... UTypes >
	tuple( tuple<UTypes...>&& other );		//右值方式

/*支持初始化列表的构造函数*/
explicit tuple (const Types&... elems);  	//左值方式
template <class... UTypes>
    explicit tuple (UTypes&&... elems);  	//右值方式

/*将pair对象转换为tuple对象*/
template< class U1, class U2 >
	tuple( const std::pair<U1, U2>& p );
template< class U1, class U2 >
	tuple( std::pair<U1, U2>&& p );

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

Example:

#include <iostream>
#include <tuple>

int main() {
    std::tuple<std::string, int> t1;    //无参构造
    std::tuple<std::string, int> t2(t1);//拷贝构造
    std::tuple<std::string, int> t3(std::make_tuple("Lily", 1));
    std::tuple<std::string, long> t4(t3);   //隐式类型转换构造的左值方式
    std::tuple<std::string, int> t5("Mike", 2); //初始化列表构造的右值方式
    std::tuple<std::string, int> t6(std::make_pair("Jack",3));  //将pair对象转换为tuple对象
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
2) make_tuple()函数

make_tuple() 函数以模板的形式定义在 头文件中,功能是创建一个 tuple 右值对象(或者临时对象)。

Exmaple:

	std::tuple<std::string, double ,int> t1 = std::make_tuple("Jack", 66.6, 88);
    auto t2 = std::make_tuple(1, "Lily", 'c');
//t2的类型实际是std::tuple<int, const char *, char>
  • 1
  • 2
  • 3

②获取tuple的值

1)std::get(std::tuple)

Example:

#include <iostream>
#include <tuple>

int main() {
    auto t1 = std::make_tuple(1, "PI", 3.14);
    std::cout << '(' << std::get<0>(t1) << ',' << std::get<1>(t1) <<
            ',' << std::get<2>(t1) <<  ')' << '\n';
    return 0;
}
/*
output: (1,PI,3.14)
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

值得注意的是,由于get的特性,tuple不支持迭代,只能通过元素索引(或tie解包)进行获取元素的值。但是给定的索引必须是在编译器就已经给定,不能在运行期进行动态传递,否则将发生编译错误

2) std::tie()

解包时,我们如果只想解某个位置的值时,可以用std::ignore占位符来表示不解某个位置的值

Example

#include <iostream>
#include <tuple>

int main() {
    auto t1 = std::make_tuple(1, "PI", 3.14);
    auto t2 = std::make_tuple(2, "MAX", 999);
    std::cout << '(' << std::get<0>(t1) << ',' << std::get<1>(t1) <<
            ',' << std::get<2>(t1) <<  ')' << '\n';
    int num = 0;
    std::string name;
    double value;
    std::tie(num, name, value) = t1;
    std::cout << '(' << num << ',' << name << ',' << value << ')' << '\n';
    num = 0, name = "", value = 0;
    std::tie(std::ignore, name, value) = t2;
    std::cout << '(' << num << ',' << name << ',' << value << ')' << '\n';
    return 0;
}
/*
output:
(1,PI,3.14)
(1,PI,3.14)
(0,MAX,999)
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

③其他方法

1)获取元素个数

可以采用std::tuple_size<T>::value来获得,其中T必须要显式给出tuple的类型;

Example:

#include <iostream>
#include <tuple>

int main() {
    auto t1 = std::make_tuple(2, "MAX", 999, 888, 65.6);
    std::cout << "The t1 has elements: " << std::tuple_size<decltype(t1)>::value << '\n';
    return 0;
}
/*
output: The t1 has elements: 5
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
2) 获取元素类型

可以直接采用std::tuple<size_t i,decltype(tuple)>::type来获取;

include <iostream>
#include <tuple>

int main() {
    auto t1 = std::make_tuple(2, "MAX", 999.9);
    std::cout << "The t1 has elements: " << std::tuple_size<decltype(t1)>::value << '\n';
    std::tuple_element<0, decltype(t1)>::type type0;
    std::tuple_element<1, decltype(t1)>::type type1;
    std::tuple_element<2, decltype(t1)>::type type2;
    type0 = std::get<0>(t1);
    type1 = std::get<1>(t1);
    type2 = std::get<2>(t1);
    std::cout << "type0 : " << type0 << '\n';
    std::cout << "type1 : " << type1 << '\n';
    std::cout << "type2 : " << type2 << '\n';
    return 0;
}
/*
output:
The t1 has elements: 3
type0 : 2
type1 : MAX
type2 : 999.9
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
3)使用tuple引用来改变tuple内元素的值

std::tuple<T1&> t3(ref&); // tuple的元素类型可以是一个引用

引用声明代表对于创建tuple的对应元素而言,改变tuple的值会影响原有变量;

Example:

#include <iostream>
#include <tuple>
#include <functional>

int main() {
    auto t1 = std::make_tuple("test", 85.8, 185);
    std::string name;
    double weight;
    int height;

    auto t2 = std::make_tuple(std::ref(name), std::ref(weight),std::ref(height)) = t1;
    std::cout << "Before change : " << '\n';
    std::cout << '(' << name << ' ' << weight << ' ' << height << ')' << '\n';

    name = "spark", weight = 95.6, height = 188;
    std::cout << "After change : " << '\n';
    std::cout << '(' << std::get<0>(t2) << ' ' << std::get<1>(t2) << ' ' << std::get<2>(t2) << ')' << '\n';
    return 0;
}
/*
output:
Before change : 
(test 85.8 185)
After change : 
(spark 95.6 188)
*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

3.参考

https://cplusplus.com/reference/tuple/

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/305868
推荐阅读
相关标签
  

闽ICP备14008679号