C++11时代的标准库快餐教程(1) - 不同类型值组成的简单列表

    xiaoxiao2025-09-23  31

    不同类型值组成的简单列表 - pair和tuple

    值对儿,就是由两个或以上的不同类型的值,组成的简单列表结构。强调不同类型,是因为同类型用数组不就是了么。最简单的值对,是只有两个值的对儿,这种结构叫做std::pair.

    两个值结对儿-std::pair

    这种简单的结构有什么用呢?答案就在于简单。我们有很多种情况下,需要的就是简单。

    key-value组合: 比如我们要在真正的容器里放键-值对(key-value),这是一个再普通不过的需求了。这时肯定犯不上为每一种这样的组合写一个新类,更不值得用更复杂的容器,能有一个非常简单的值对模板类是最方便的。函数返回值:C程序员可能非常羡慕其他语言,比如Go语言或很多脚本语言,返回值可以返回多个值。最常用的用法就是,先返回一个错误码,然后才是真正的返回值。

    在C++模板库里,也确实就是这么做的。针对第一种情况,C++标准库中的map结构,如map和multimap的每一个元素,都是pair对象。而要返回多于一个值的时候,比如Set的insert函数,就返回一个pair

    pair的构造

    最简单的pair构造法,就是使用make_pair函数:

        auto test1 = std::make_pair(1,"test1");     auto test2 = std::make_pair(2,"test2");

    C++11的auto关键字发挥功力了,我们甚至都不需要写std::pair的模板定义,直接用std::make_pair去构造,类型请auto自己去推断。

    我们再来个函数返回值的:

    std::pair<int,std::string> checkValue(int value){     if(value<1000){         return std::make_pair(0, "checked pass");     }else{         return std::make_pair(-1, "checked failed");     } }

    pair的使用

    pair很简单,通过pair.first和pair.second就可以访问对象的第一个值和第二个值。例,处理下我们上面例子的函数返回值:

        auto result = checkValue(100);     if(result.first==0){         std::cout << "Checked pass! The message is: "<<result.second <<"\n";     }

    三个以上的值: std::tuple

    pair只能用于两个值,但是有时候我们需要多于两个值怎么办?这时候C++11又送了一份大礼给我们,C++11支持模板参数不指定具体个数个参数。所以C++98只能支持10个参数的限制再也没有了,现在的tuple可以支持多个参数。std::get<0>这样的语法在pair时显得多余,但是推广到tuple上,它就可以大显身手了。

    一句话说tuple,就是把pair的两个参数扩展成三个以上就可以了。比如我们想在函数返回值里再多加几个值,把pair换成tuple,make_pair换成make_tuple,其余都照旧就是了。

    std::tuple<int, std::string, std::string,int> checkValueWithDetails(int value){     if(value<1000){         return std::make_tuple(0,"checking passed","normal case",value);     }else{         return std::make_tuple(-1,"checking failed","bad case",value);     } }

    返回值使用的时候,还是get<>()函数。当然这时候first和second已经没什么意义了,统一用get<>():

        auto result3 = checkValueWithDetails(1);     if(std::get<0>(result3)==0){         std::cout<< "Checking passed! The message is: "<<std::get<1>(result3) << "The detail info is:" << std::get<2>(result3)<<"\n";     }

    std::tie 批处理

    我们想把tuple的值取出来赋到各个变量中去,一个一个get<>太麻烦,有没有办法一次性搞定?当然有啦,我们通过std::tie函数来做这个事情:

        auto result4 = checkValueWithDetails(-1);     int resultValue;     std::string message;     std::string details;     int initValue;     std::tie(resultValue,message,details,initValue)=result4;

    写起来是不是有种在用脚本语言的感觉?如果其中有些值我们不关注,那就用std::ignore来占位,就像Go语言中的"_"一样,就不用再定义个无用的变量了。比如上例,假如我们对message不感兴趣,我们就这么写:

        std::tie(resultValue,std::ignore,details,initValue)=result4;

    std::ignore可以适用于任何类型。

    好啦,快餐教程就讲这么多。我们复习一下:

    std::pair是C++98就有的功能,std::tuple是TR1新增的。C++11的两个特性为pair和tuple带来很大帮助,一个是auto的类型推断可以帮助我们少写代码,二是C++11支持变参数的模板,使得理论上可以支持任意多个数量的参数。tuple来自boost库,但是没有C++11支持的boost::tuple和TR1的std::tuple支持的参数个数是受限的。通过std::make_pair和std::make_tuple可以方便地构造pair和tuple对象。std::tie()函数可用于将pair或tuple中的值绑定到一些变量上,不关心的值可以用std::ignore来忽略。
    最新回复(0)