c++tuple模版元编程分析

时间:2021-08-07 18:39:50

c++的tuple可以装载任何的类型,用法示例:

std::tuple<int, char> a(10, 'x');  
std::cout << " " << std::get<0>(a);  
std::cout << " " << std::get<1>(b);  

先上一个极简的tuple实现

#include <stdio.h>

template <typename... Types>
struct mytuple {

};

template <typename T, typename... Types>
struct mytuple<T, Types...> : mytuple<Types...>{
	mytuple(T v, Types... args) : _val(v), mytuple<Types...>(args...) {

	}

	T       _val;
};

template <typename T>
struct mytuple<T> {
	mytuple(T v) : _val(v) {

	}

	T       _val;
};

template <size_t n, typename... Types>
struct mytuple_element {
};

template <size_t n, typename T, typename... Types>
struct mytuple_element<n, T, Types...> {
	typedef typename mytuple_element<n - 1, Types...>::type type;
	typedef typename mytuple_element<n - 1, Types...>::tuple_type tuple_type;
};

template <typename T, typename... Types>
struct mytuple_element<0, T, Types...> {
	typedef T type;
	typedef mytuple<T, Types...> tuple_type;
};

template<size_t n, typename... Types>
typename mytuple_element<n, Types...>::type myget(const mytuple<Types...>& tup) {
	return ((typename mytuple_element<n, Types...>::tuple_type&)tup)._val;
}

int main()
{
	mytuple<int, float, char> vv(1, 2.0f, 'c');
	auto vvv = myget<0>(vv);
	printf("%d\n", vvv);
	auto vv2 = myget<2>(vv);
	printf("%c\n", vv2);
	getchar();
	return 0;
}

主要是两个关键,一个是如何构造,一个是get<n>时如何拆分。

如何构造

下面这个mytule会继承另一个模板mytule,并且把模板的参数进行拆分

mytuple<T, Types...> : mytuple<Types...>

假如是tuple<int,float,char>将会继承tuple<float,char>,tuple<float,char>又会继承tuple<char>,因为是继承,所以子类tuple<int,float,char>跟父类是可以转换的。递归的终点是tuple<>。

最终是一个包含的状态

c++tuple模版元编程分析


如何拆分

template<size_t n, typename... Types>
typename mytuple_element<n, Types...>::type myget(const mytuple<Types...>& tup) {
	return ((typename mytuple_element<n, Types...>::tuple_type&)tup)._val;
}

return的返回值是获取mytuple_element的tuple_type强转成tuple类型。mytuple_element有两个类模板

struct mytuple_element<n, T, Types...> {
	typedef typename mytuple_element<n - 1, Types...>::type type;
	typedef typename mytuple_element<n - 1, Types...>::tuple_type tuple_type;
};

template <typename T, typename... Types>
struct mytuple_element<0, T, Types...> {
	typedef T type;
	typedef mytuple<T, Types...> tuple_type;
};

这2个模板是递归的,第一个接受参数,一直递归N-1直到参数直到为0最终获取到T的类型。

栗子:定义一个tuple<int,float,char>,调用get<2>(tuple)

第一次

mytuple_element<2,int,Types...(float,char)>=> mytuple_element<1,Types...(float,char)>,int被舍弃

第二次

mytuple_element<1, float ,Types...(char)>   => mytuple_element<0, char>,float被舍弃

N至此为0,然后此时mytuple_element<0, char>对应了mytuple_element<0, T, Types...>模板类

最终返回mutuple<char>tuple类型,因为子类可以转化为父类tuple<int,float,char>转化成mutuple<char>tuple,然后调用mutuple<char>tuple(tuple);最终取得char对应的值。

其实不用get方法,可以通过强转的方式获得指定的值,比如想获得double的值

	mytuple<int, double, char> m(10,99.99,'b');
	mytuple<double, char> m1 = (mytuple<double, char>)m;
	std::cout << m1._val;
输出99.99。


参考文章:

http://www.newsmth.net/bbstcon.php?board=CPlusPlus&gid=399280

https://blog.csdn.net/libgod/article/details/16980559

http://www.jb51.net/article/70740.htm

https://www.cnblogs.com/flytrace/p/3574647.html