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

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

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

两个值结对儿-std::pair

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

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

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

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::get<>()函数来获取第一个和第二个值. pair.first等价于std::get<0>(pair),pair.second等价于std::get<1>(pair).
例:

    auto result2 = checkValue(1000);
    if(std::get<0>(result2)!=0){
        std::cout << "Checking failed. The message is:" << (std::get<1>(result2)) <<"\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可以适用于任何类型。

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

  1. std::pair是C++98就有的功能,std::tuple是TR1新增的。C++11的两个特性为pair和tuple带来很大帮助,一个是auto的类型推断可以帮助我们少写代码,二是C++11支持变参数的模板,使得理论上可以支持任意多个数量的参数。tuple来自boost库,但是没有C++11支持的boost::tuple和TR1的std::tuple支持的参数个数是受限的。
  2. 通过std::make_pair和std::make_tuple可以方便地构造pair和tuple对象。
  3. std::tie()函数可用于将pair或tuple中的值绑定到一些变量上,不关心的值可以用std::ignore来忽略。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容