c++新特性 深入元组

1.元组简介

tuple是一个固定大小的不同类型值的集合,是泛化的std::pair。我们也可以把他当做一个通用的结构体来用,不需要创建结构体又获取结构体的特征,在某些情况下可以取代结构体使程序更简洁,直观。std::tuple理论上可以有无数个任意类型的成员变量,而std::pair只能是2个成员,因此在需要保存3个及以上的数据时就需要使用tuple元组了。

    tuple(元组)在c++11中开始引用的。tuple看似简单,其实它是简约而不简单,可以说它是c++11中一个既简单又复杂的东东,关于它简单的一面是它很容易使用,复杂的一面是它内部隐藏了太多细节,要揭开它神秘的面纱时又比较困难。

2.tuple的创建以及初始化

std::string name;
std::tuple<string &, int> tpRef(name, 30);
// 对tpRef第一个元素赋值,同时name也被赋值 - 引用
std::get<0>(tpRef) = "Sven";
 
// name输出也是Sven
std::cout << "name: " << name << '\n';

 3.有关tuple的操作

 3.1等价结构体

     开篇讲过在某些时候tuple可以等同于结构体一样使用,这样既方便又快捷。如

struct person {
    char *m_name;
    char *m_addr;
    int  *m_ages;
};
 
//可以用tuple来表示这样的一个结构类型,作用是一样的。
std::tuple<const char *, const char *, int>

 3.2获取元组取个数和合并元组

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";
}

3.3获取元组类型

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

3.4解包和引用

#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

3.5遍历

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());
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值