实现可变参数模板类Tuple

  参考资料:【C++】C++11可变参数模板(函数模板、类模板)

可变参数模板类机制

  C++11极大的增强了模板的功能,支持了可变参数模板类,允许定义包含0到任意个模板参数,其类似于函数的可变参数机制。

C++11的tuple类

  C++11中引入了tuple类,其功能类似于Python中的元组,能够存放任意类型和个数的元素。这里给出cplusplus.com的示例代码以简单介绍该类的使用方法。

代码示例

// tuple example
#include <iostream>     // std::cout
#include <tuple>        // std::tuple, std::get, std::tie, std::ignore

int main ()
{
  std::tuple<int,char> foo (10,'x');
  auto bar = std::make_tuple ("test", 3.1, 14, 'y');

  std::get<2>(bar) = 100;                                    // access element

  int myint; char mychar;

  std::tie (myint, mychar) = foo;                            // unpack elements
  std::tie (std::ignore, std::ignore, myint, mychar) = bar;  // unpack (with ignore)

  mychar = std::get<3>(bar);

  std::get<0>(foo) = std::get<2>(bar);
  std::get<1>(foo) = mychar;

  std::cout << "foo contains: ";
  std::cout << std::get<0>(foo) << ' ';
  std::cout << std::get<1>(foo) << '\n';

  return 0;
}

  运行结果:

foo contains: 100 y

C++实现Tuple

  tuple的实现便是基于可变参数模板类机制,这里我们使用这一机制实现一个自己的Tuple类,具体的方式有两种:继承方式和组合方式。

继承方式实现

  继承方式是通过递归继承的方式来构建可变参数模板类的,我们需要定义一个可变参数模板类,再定义一个空包模板类,然后再定义递归展开的模板类,以此来实现可变参数模板类,具体如下所示:

代码测试

  继承方式实现Tuple类:

#include<bits/stdc++.h>
using namespace std;
//定义一个可变参数模板类
template<typename... Types>
class Tuple;
//定义一个空参数的模板类,
template<>
class Tuple<>{
public:
    friend ostream& operator<<(ostream& out, Tuple<> T){//作为递归最下层的输出,也需要实现该操作符
        return out;
    }
};

//递归展开 Tuple 中的元素
template<typename TypeZero,typename... Types>
class Tuple<TypeZero,Types...>:private Tuple<Types...>{
    typedef Tuple<Types...> inherited;                  //给继承的类起一个别名
protected:
    TypeZero head_v;
public:
    Tuple(){}
    Tuple(TypeZero v,Types... values):head_v(v),inherited(values...){}
    TypeZero& head(){return head_v;}                    //获取元组的第一个元素
    inherited& tail(){return *this;}                    //获取元组除了第一个元素之外的元素,基类元素和派生类的其实地址是一样的,基类的引用或者指针可以指向派生类
    friend ostream& operator<<(ostream& os,Tuple& t){   //友元函数输出整个tuple,需要在空元组中定义该运算符重载函数
        os<<t.head()<< " "<<t.tail();
        return os;
    }
};

int main(){
    Tuple<int,double,string,string> t(1,2.0,"hello", "world");
    cout<<t<<endl;
    return 0;
}

  执行结果:

1 2 hello world

组合方式实现

  组合方式是将可变参数模板类作为一个成员变量来构建的,这样一层一层的叠加最终形成一个可变参数模板类,具体代码如下所示:

代码测试

#include<bits/stdc++.h>
using namespace std;
//定义一个可变参数模板类
template<typename... Types>
class Tuple;
//定义一个空参数的模板类,
template<>
class Tuple<>{
public:
    friend ostream& operator<<(ostream& out, Tuple<> T){//作为递归最下层的输出,也需要实现该操作符
        return out;
    }
};

//递归展开 Tuple 中的元素
template<typename TypeZero,typename... Types>
class Tuple<TypeZero,Types...>{
    typedef Tuple<Types...> composited;                  //给继承的类起一个别名
protected:
    composited composited_m;
    TypeZero head_v;
public:
    Tuple(){}
    Tuple(TypeZero v,Types... values):head_v(v),composited_m(values...){}
    TypeZero& head(){return head_v;}                            //获取元组的第一个元素
    composited& tail(){return composited_m;}                    //获取元组除了第一个元素之外的元素
    friend ostream& operator<<(ostream& os,Tuple& t){           //友元函数输出整个tuple,需要在空元组中定义该运算符重载函数
        os<<t.head()<< " "<<t.tail();
        return os;
    }
};

int main(){
    Tuple<int,double,string,string> t(1,2.0,"hello", "world");
    cout<<t<<endl;
    return 0;
}

  执行结果:

1 2 hello world

当珍惜每一片时光~