背景
tuple是C++一个模板类,和struct和class的区别是,作为容器不用你提前定义里面的成员变量类型以及个数。
- 好处
这样的好处是,使用很灵活,写代码的人可以把任意的数据类型打包成一个容器
// strcut
struct Test
{
int a;
float b;
double c;
}
Test t;
// tuple
using Test = std::tuple<int, float, double> ;\
Test t1(1, 1.0f, 2.0)
auto t2 = std::make_tuple(1, 1.0f, 2.0); // make_tuple也可以接受可变长参数包
- 坏处
之所以可以做到随意个数和数据类型的容器,原因是C++在编译器递归生成了n个tuple类,分别是, <int, float>,<int, float, double>, 所以不是没有"struct", 而是为了灵活生成了更多的数据结构,因为生成的tuple结构特殊,必须使用std::get(t1)才可以去数值,而K必须是一个编译器的数值,因为这个玩意必须要在编译期确定,具体的tuple实现原理可以看《元模板编程》书中的例子。
何时使用
tuple最常用的就是在变成参数中使用,因为函数只能保证最后一个参数是可变长的包,为了保证参数列表中的中间数据也是可变长,那么中间的数据就必须用tuple给包一下,下面就是一个简单tuple常见的使用例子,如果需要可以在里面找到对应的操作。
#include <iostream>
#include <tuple>
void func1(int in1, int in2, int arg) {};
template<typename T>
void set_num(T a){ std::cout<<a<<std::endl;};
template<typename... Inputs, typename... Args, size_t... I, size_t... J>
void test(std::tuple<Inputs...> input, std::index_sequence<I...>, std::tuple<Args...> args, std::index_sequence<J...>)
{
(set_num(std::get<I>(args)), ...);
}
template<typename F, typename... Inputs, typename Tuple>
void register_op(F f, std::tuple<Inputs...> input, Tuple args)
{
test(input, std::make_index_sequence<std::tuple_size<Tuple>::value>(), args, std::make_index_sequence<5>());
};
template<typename F, typename IN, typename... Args >
void register_func(F f, IN* input, Args... args)
{
return register_op(f, std::make_tuple(input), std::make_tuple(args...));
}
int main()
{
int input1 = 1;
int input2 = 2;
float a = 3.2;
double b = 3.1;
register_func(func1, &input1, a, b);
}
后记
元模板编程看起来是很秀,其实本质就是编译器帮你做一些事情,只要理清楚本质在运行时候做啥,模板编程就是纸老虎,喜欢的朋友可以持续关注我,后续会更新最新的C++技术