窥视C++细节-使用tie函数解包pair对象的原理

示例

这是http://www.cplusplus.com/reference/tuple/tie/?kw=tie中的一个std::tie()函数的示例。

#include <iostream>     // std::cout
#include <tuple>        // std::tuple, std::make_tuple, std::tie

int main ()
{
  int myint;
  char mychar;

  std::tuple<int,float,char> mytuple;

  mytuple = std::make_tuple (10, 2.6, 'a');          // packing values into tuple

  std::tie (myint, std::ignore, mychar) = mytuple;   // unpacking tuple into variables

  std::cout << "myint contains: " << myint << '\n';
  std::cout << "mychar contains: " << mychar << '\n';

  return 0;
}
myint contains: 10
mychar contains: a

std::tie函数

std::tie函数可以用于建立一个由reference构成的tuple,也可以用于tuple的解包。

可能的实现:

template <typename... Args>
auto tie(Args&... args) {
    return std::tuple<Args&...>(args...);
}

std::tie函数,将创建一个由reference构成的匿名tuple对象,并将其返回。

这里比较有意思的是,std::tie创建的匿名tuple对象,其内部通过引用和传入的参数想关联,随意一方的改动,对方可以感知,是同步的。

我们使用一个简单的示例模式一下,代码如下:

class A
{
public:
    A(int& i)
        :ri(i){}

    void set(int x){
        ri = x;
    }
    
private:
    int & ri;
};

int main()
{
    int i = 10;
    A a(i);
    
    a.set(20);

    cout<<"i = "<<i<<endl;

    return 0;
}
i = 20

通过传递变量的引用,使得在多处可以对同一个变量进行修改。

  std::tuple<int,float,char> mytuple;
  mytuple = std::make_tuple (10, 2.6, 'a');         

先是使用默认构造器,创建mytuple对象。

使用make_tuple可以快速的创建tuple对象,同时make_tuple是一个模板参数,省去了指定参数的类型。

mytuple = std::make_tuple<int,float,char>(10,2.6,'a');

这样也是可以的

make_tuple将返回的tuple对象,赋值给mytuple,将发生一次赋值运算符重载。此后mytuple就保存了10,2.6,'a’这三个数据。

std::tie (myint, std::ignore, mychar) = mytuple;

tie将返回一个临时的匿名的tuple对象,这个tuple对象和myint、mychar变量通过引用进行关联,如果对这个临时匿名的tuple的修改,myint、mychar都可以感知。

mytuple将赋值给匿名的临时tuple对象,也就是mytuple中的值分别赋给了myint、std::ignore、mychar。

本行执行完毕,std::tie函数返回的临时对象就被销毁了。同时myint变为了10,mychar变为了’a’。
在这里插入图片描述

std::ignore

可能的实现

namespace detail {
struct ignore_t {
    template <typename T>
    const ignore_t& operator=(const T&) const { return *this; }
};
}
const detail::ignore_t ignore;

std::ignores是detail::ignore_t类型的一个const类型的实例对象。detail::ignore_t类内部提供了模板类型operator=,任意类的对象都可以给它赋值,但它的赋值什么也不做,只是单纯的返回自己,所以所有给它的值相当于全部被忽略了。这里之所以返回*this是为了实现连等式。

std::tie (myint, std::ignore, mychar) = mytuple;

在执行tuple赋值运算符重载的时候,mytuple将第二个值赋值给了std::ignore对象,这导致上面函数的调用,但是由于这个函数什么不做,所以mytuple中的第二个值就被忽略了。

class A
{
public:
};

class B
{
public:
};

int main ()
{
  A a;
  B b;

  int i = 100;
  float f = 3.14;
 
  std::ignore = i;
  std::ignore = f;
  std::ignore = a;
  std::ignore = b;

  return 0;
}

任意类型的对象都可以赋值给ignore,但什么反应也不会有。

std::pair和std::tuple互转

可以使用一个pair作为初值,初始化一个双元素tuple,也可以将一个pair赋值给一个双元素tuple。

pair<int,string> studentPair(1001,"Bob");
tuple<int,string> studentTuple;

studentTuple = studentPair;

cout<<"id   = "<<get<0>(studentTuple)<<endl;
cout<<"name = "<<get<1>(studentTuple)<<endl;
id   = 1001
name = Bob

解包pair返回值

#include <iostream>    
#include <tuple>     
#include <set>

int main ()
{
    set<int> si;
    
    bool inserted;
    
    std::tie(std::ignore,inserted) = si.insert(10);
    if(inserted){
        cout<<"Value was inserted successfully"<<endl;
    }

    //set中已经有了10,再次插入10,将失败。
    std::tie(std::ignore,inserted) = si.insert(10);
    if(!inserted){
        cout<<"Value was inserted failed"<<endl;
    }
    
  return 0;
}
Value was inserted successfully
Value was inserted failed

set成员函数insert的返回值是一个pair。pair.first返回插入位置的迭代器,pair.second表示是否插入成功。

现在通过std::tie函数只解包出是否插入成功。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值