va_list ptr
: 定义一个指向可变参数列表的指针
va_start(ptr, a)
:初始化指针,其中第二个参数为函数可变参数列表之前的固定参数
va_arg(ptr,int)
:取出指针指向的元素,第二个参数为元素的类型,返回值为取出的元素,同时指针后移。
va_end(ptr)
: 还原ptr指针
#include
// 确定:要知道有多少个参数,并且要知道每个参数的类型
void print(int a, ...)
{
va_list ptr; // 定义一个指向可变参数的指针
va_start(ptr, a); // 初始化指针,使得指针指向固定参数a后面的可变参数列表
int tmpInt = va_arg(ptr, int); // 取指针指向的可变参数,类型为int; 同时ptr向后移动
char tmpChar = va_arg(ptr, char); // 取当前指向的类型为char
va_end(ptr);
cout << tmpInt << ", " << tmpChar << endl;
}
int main()
{
print(3, 3, 'a');
getchar();
return 0;
}
弊端,必须要知道可变参数的个数和参数类型
_Check_return_opt_
_CRT_STDIO_INLINE int __CRTDECL printf( _In_z_ _Printf_format_string_ char const* const _Format, ...)
VA_ARGS:
C99新增的宏,用来替换宏定义中的可变参数列表
#define LOG(format, ...) fprintf(stdout, format, __VA_ARGS__)
LOG("%d, %c", 2, 'x'); // 2 x
#define LOG2(x) printf("LOG2 "#x" %d \n", x); // #会吧参数转换成字符串
int tmpInt = 100;
LOG2(55); // LOG2 55 55
LOG2(value); // LOG2 Value 100
// ##当可变参数为0时去掉逗号和后面的数据
#define LOG_TYPE(format, ...) do{ \
printf(format, ##__VA_ARGS__); \
\
} while(0)
# 将变量转化成字符串
## 用于宏中的参数替换, 如 #define test(x) f(a##x) . test3 => f(a3)
#include
#define MODEL_NAEM "model_name"
#define err_print(fmt, ...) \
printf("[ERROR!] ["MODEL_NAEM": (fun)%s, (line)%d] " fmt, __func__, __LINE__, ##__VA_ARGS__)
// 注意fmt和前面字符串之间的链接方式
int main(void){
err_print("i = %d\n", 5);
return 0;
}
#include
#include
using namespace std;
// 递归结束
template<typename T>
void showOne(T t)
{
cout << t << endl;
}
template<typename T, typename...Ts>
void showOne(T t, Ts... ts)
{
cout << t << ", ";
showOne(ts...);
}
template<typename... T>
void show(T... ts)
{
showOne(ts...);
}
int main()
{
string s("dddd");
show("int", 2, 2.32, s);
}
const 引用版本
template<typename T>
void disPlayOne(T t)
{
cout << t << endl;
}
template<typename T1, typename... Ts>
void disPlayOne(const T1 &t1, const Ts&... ts)
{
cout << t1 << ", ";
disPlayOne(ts...);
}
template<typename... T>
void disPlay(const T&... ts)
{
disPlayOne(ts...);
}
int main()
{
string s("dddd");
disPlay("int", 2, 2.32, s);
}
右值引用版本
#include
#include
#include
using namespace std;
template<typename T>
void print(T &&t)
{
cout << t << endl;
}
template<typename T>
void printargs(T &&arg)
{
print(forward<T>(arg));
}
template<typename T, typename... Ts>
void printargs(T &&arg, Ts&&... args)
{
print(forward<T>(arg));
printargs(forward<Ts>(args)...); // 注意转发时候的书写格式
}
int main()
{
char ch = 'a';
string ss("abc");
printargs(1, 34, 52, ch, ss);
return 0;
}
#include
#include
#include
#include
using namespace std;
template<typename T>
void print(T &&t)
{
cout << t << endl;
}
template<typename... Ts>
void expand(Ts... ts)
{
int arr[] = {(print(ts),0)...}; // 会被展开为 {(print(ts1), 0), (print(ts2), 0), (print(ts2), 0), ...}
//或者改进为std::initializer_list{(printarg(args), 0)...};
//用lambda表达式实现(gcc4.8.6编译报错)
std::initializer_list<int>{([&] {cout << args << endl; }(), 0)...};
}
int main()
{
expand(1, 2, 4, 'a', "ddfa");
return 0;
}
template <typename... Ts>
class ClassA;
// 可变参数模板类可以携带多个不同的参数
ClassA<int>
classA<int, char>
ClassA<>
//----------------------------
// 前向声明
template <typename... Ts>
class ClassTs;
// 特化处理,递归终止函数
template <typename T>
class ClassTs<T>
{
public:
enum { value = sizeof(T) };
};
template <typename T, typename... Ts>
class ClassTs<T, Ts...>
{
public:
enum { value = ClassTs<T>::value + ClassTs<Ts...>::value };
};
int main()
{
cout << ClassTs<int, char, char, int>::value << endl;
return 0;
}
参考:
c++11——可变参数模板
C 语言 define 变参__VA_ARGS__使用
#、##、__VA_ARGS__和##__VA_ARGS__的作用
c++反射机制
c++可变参数模板
备注:之后看了模板再来补充