变长参数模板是C++14新增的特性。具体定义就不赘述了,我们更多关心的是这种特性用在什么地方。
下面直接列出代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| #include <cstdint> #include <iostream> #include <functional>
template<typename T, typename... Args> bool Function(T t, Args... args) { std::cout << t << std::endl; Function(args...); return true; }
template<typename T> bool Function(T t) { std::cout << t << std::endl; return true; }
template<typename... Args> void Dummy(Args... args) {}
template<typename... Args> void TestVaradicTemplate(Args... args) { ::printf("---------------- Sample 1:\n"); Function(args...);
::printf("---------------- Sample 2:\n"); Dummy(Function(args)...);
::printf("---------------- Sample 3:\n"); auto exeFunc = [](auto t) { std::cout << t << std::endl; return 1; }; auto dummyFunc = [](auto... t) {};
dummyFunc(exeFunc(args)...); }
int main() { TestVaradicTemplate<bool, int, const char*>(false, 1024, "Hello World");
return 0; }
|
下面是输出:
有几点需要说明:
- Sample 1和Sample 2是两种最常见的使用方式,前者侧重执行功能,后者侧重参数传递。
- Sample 2中展示了一种变参展开并执行功能的技巧,同时参数可以继续传递下去。可以看到,结果中参数展开顺序是从右至左的,而若使用Clang编译,顺序会是从左至右,这依赖于编译器对函数参数求值顺序的实现。也正因如此,执行功能如果在意参数顺序,需格外注意。
- Sample 3是Sample 2的lambda实现形式。在某些情况下,直接在函数中采用lambda实现,会更灵活简洁。其中,exeFunc的return是必须的,否则返回类型为void,dummyFunc将无法接收其作为参数。
变长参数模板是一种十分有用的特性,尤其在写公共库的时候,这点在MetaLua中得到了大量体现。