// 变长参数模板和变长参数
// 部分 Code 来自《现代 C++ 教程:高速上手 C++11/14/17/20》,这里作为笔记记录。
#include <iostream>
#include <string>
// 变长参数解包:
/*************************/
/* Method 1: 递归模板函数 */
/*************************/
// 递归是非常容易想到的一种手段,也是最经典的处理方法。这种方法不断递归地向函数传递模板参
// 数,进而达到递归遍历所有模板参数的目的。
#ifdef __cpp_if_constexpr // or #if __cplusplus >= 201606L
template<typename T, typename... Args>
void printf1(T val, Args... args)
{
std::cout << val << std::endl;
if constexpr (sizeof...(args) > 0) // for c++17
printf1(args...);
}
#else
// c++17 之前,递归函数模板需要单独定义终止递归的函数,即只有一个参数的printf1
template<typename T>
void printf1(T val)
{
std::cout << val << std::endl;
}
template<typename T, typename... Args>
void printf1(T val, Args... args)
{
std::cout << val << std::endl;
printf1(args...);
}
#endif
/*************************/
/* Method 2: 初始化列表展开 */
/*************************/
// 递归模板函数是一种标准的做法,但缺点显而易见的在于必须定义一个终止递归的函数。
// 这里介绍一种使用初始化列表展开的黑魔法。
template<typename T, typename... Args>
auto printf2(T value, Args... args) {
std::cout << value << std::endl;
std::initializer_list<T>{
(
[&args] {
std::cout << args << std::endl;
}(),
value
)...
};
}
/********************/
/* c++17 折叠表达式 */
/********************/
#ifdef __cpp_fold_expressions // or #if __cplusplus >= 201411L
template<typename ...Args>
auto sum(Args... args)
{
// return (args + ...); // for c++17
return (... + args); // same
}
template<typename ...Args>
void printer(Args&&... args) {
(std::cout << ... << args) << '\n';
}
#endif
int main()
{
std::cout << "---\n";
printf1(1);
printf1(2, 3, "str", 1.2f);
std::cout << "---\n";
printf2<int, int, std::string>(1, 2, "hello");
#if __cplusplus >= 201411L // or #ifdef __cpp_fold_expressions
std::cout << "---\n";
std::cout << sum(2, 6, 5.5f) << std::endl;
printer("cpp", ' ', 'a', ' ', 2.3f, ' ', 2);
#endif
return 0;
}