赞
踩
tuple是一个固定大小的不同类型值的集合,是泛化的std::pair。我们也可以把他当做一个通用的结构体来用,不需要创建结构体又获取结构体的特征,在某些情况下可以取代结构体使程序更简洁,直观。std::tuple理论上可以有无数个任意类型的成员变量,而std::pair只能是2个成员,因此在需要保存3个及以上的数据时就需要使用tuple元组了。
tuple(元组)在c++11中开始引用的。tuple看似简单,其实它是简约而不简单,可以说它是c++11中一个既简单又复杂的东东,关于它简单的一面是它很容易使用,复杂的一面是它内部隐藏了太多细节,要揭开它神秘的面纱时又比较困难。
std::string name;
std::tuple<string &, int> tpRef(name, 30);
// 对tpRef第一个元素赋值,同时name也被赋值 - 引用
std::get<0>(tpRef) = "Sven";
// name输出也是Sven
std::cout << "name: " << name << '\n';
开篇讲过在某些时候tuple可以等同于结构体一样使用,这样既方便又快捷。如
- struct person {
- char *m_name;
- char *m_addr;
- int *m_ages;
- };
-
- //可以用tuple来表示这样的一个结构类型,作用是一样的。
- std::tuple<const char *, const char *, int>
tuple_size<decltype(u)>::value;
tuple_cat;
- #include<tuple>
- #include<iostream>
-
- int main()
- {
- std::tuple<double,char,std::string> u(2.6,'c',"王五");
- std::cout<<std::tuple_size<decltype(u)>::value<<std::endl;
- std::tuple<double,char,std::string> v(1.6,'d',"陈六");
- auto new_tuple=std::tuple_cat(std::move(u),std::move(v));
- std::cout<<std::get<5>(new_tuple)<<"\n";
- }
- std::tuple<std::string, int> tp("Sven", 20);
-
- // 得到第二个元素类型
-
- std::tuple_element<1, decltype(tp)>::type ages; // ages就为int类型
-
- ages = std::get<1>(tp);
-
- std::cout << "ages: " << ages << '\n';
-
- //输出结果:
- ages: 20
- #include<tuple>
- #include<iostream>
- #include<variant>
-
- auto get_student(int id)
- {
- if(id==0)
- return std::make_tuple(3.8,'A',"张三");
- if(id==1)
- return std::make_tuple(3.3,'c',"李四");
- if(id==2)
- return std::make_tuple(2.9,'d',"王五");
- return std::make_tuple(0.0,'D',"null");
-
- }
- int main()
- {
- auto student=get_student(0);
- std::cout << "ID: 0, "
- << "GPA: " << std::get<0>(student) << ", "
- << " 成绩: " << std::get<1>(student) << ", "
- << " 姓名: " << std::get<2>(student) << '\n';
- double gpa;
- char grade;
- std::string name;
-
- std::tie(gpa,grade,name)=get_student(1);
- std::cout << "ID: 1, "
- << "GPA: " << gpa << ", "
- << " 成绩: " << grade << ", "
- << " 姓名: " << name << "\n";
-
-
- }
- //output
- ID: 0, GPA: 3.8, 成绩: A, 姓名: 张三
- ID: 1, GPA: 3.3, 成绩: c, 姓名: 李四
但有时候tuple包含的多个元素时只需要其中的一个或两个元素,如此可以通过std::ignore进行变量占位,这样将会忽略提取对应的元素
- #include <iostream>
- #include <tuple>
- #include <utility>
-
- int main(int argc, char **argv) {
- std::tuple<std::string, int, std::string, int> tp;
- tp = std::make_tuple("Sven", 25, "Shanghai", 21);
-
- // 定义接收变量
- std::string name;
- std::string addr;
- int ages;
- int areaCode = 110;
-
- std::tie(name, ages, std::ignore, std::ignore) = tp;
- std::cout << "Output: " << '\n';
- std::cout << "name: " << name <<", ";
- std::cout << "addr: " << addr << ", ";
- std::cout << "ages: " << ages << ", ";
- std::cout << "areaCode: " << areaCode << '\n';
-
- return 0;
- }
-
- //输出结果:
- Output:
- name: Sven, addr: , ages: 25, areaCode: 110
tuple不支持迭代,只能通过元素索引(或tie解包)进行获取元素的值。但是给定的索引必须是在编译器就已经给定,不能在运行期进行动态传递,否则将发生编译错误:
tuple不支持迭代,只能通过元素索引(或tie解包)进行获取元素的值。但是给定的索引必须是在编译器就已经给定,不能在运行期进行动态传递,否则将发生编译错误:
正确遍历:
- // 帮助程序用于将元组转换为可变参数模板函数参数
- // sequence_generator<3>::type will be sequence<0, 1, 2>.
- template <int...>
- struct sequence {};
- template <int N, int... S>
- struct sequence_generator : sequence_generator<N - 1, N - 1, S...> {};
- template <int... S>
- struct sequence_generator<0, S...> {
- typedef sequence<S...> type;
- };
-
- template<typename T, typename F, int... S>
- void for_each(T&& t, F f, sequence<S...>)
- {
- auto l = { (f(std::get<S>(t)), 0)... };
- }
-
- template<typename... Args, typename F>
- void for_each_in_tuple(std::tuple<Args...> const& t, F f)
- {
- for_each(t, f, typename sequence_generator<sizeof...(Args)>::type());
- }
-
- struct functor {
- template<typename T>
- void operator()(T&& t)
- {
- std::cout << t << std::endl;
- }
- };
-
- int main()
- {
- std::tuple<double, char, std::string> t = std::make_tuple(3.14, 'A', "StoneLiu");
- for_each_in_tuple(t, functor());
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。