C/C++__VA_ARGS__学习--自动打印函数的参数和返回值

发布于:2024-05-10 ⋅ 阅读:(22) ⋅ 点赞:(0)

C/C++__VA_ARGS__学习--自动打印函数的参数和返回值

通过__VA_ARGS__,自动打印函数的参数和返回值

一.参考

二.输出

input:A StructA= StructA[1,2,3,4,10,11,12,13,]
input:B StructB*= StructB[26,27,28,29,StructA[1,2,3,4,10,11,12,13,]]
input:C int= 1000
input:D float= 2000.2
output:ret "StructA"= StructA[101,2,3,4,10,11,12,13,]

三.代码

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <iostream>
#include <string>
#include <algorithm>

#define IDENTITY(x) x
#define FL_CONCAT(x, y) x##y

// 计算 __VA_ARGS__ 参数个数,最大支持64个参数 https://blog.csdn.net/10km/article/details/80769615
#define FL_TYPEVALUES_COUNT(...) FL_INTERNAL_ARG_COUNT_PRIVATE(0, ##__VA_ARGS__,\
	64, 63, 62, 61, 60, \
	59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
	49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
	39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \
	29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
	19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
	 9,  8,  7,  6,  5,  4,  3,  2,  1,  0)

#define FL_INTERNAL_ARG_COUNT_PRIVATE(\
	 _0,  _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, _41, _42, _43, _44, _45, _46, _47, _48, _49, \
	_50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \
	_60, _61, _62, _63, _64, N, ...) N
					   
#define FL_TYPEVALUES0()
#define FL_TYPEVALUES2(t, v) t v
#define FL_TYPEVALUES4(t, v, ...)        FL_TYPEVALUES2(t, v), IDENTITY(FL_TYPEVALUES2(__VA_ARGS__))
#define FL_TYPEVALUES6(t, v, ...)        FL_TYPEVALUES2(t, v), IDENTITY(FL_TYPEVALUES4(__VA_ARGS__))
#define FL_TYPEVALUES8(t, v, ...)        FL_TYPEVALUES2(t, v), IDENTITY(FL_TYPEVALUES6(__VA_ARGS__))
#define FL_TYPEVALUES10(t, v, ...)       FL_TYPEVALUES2(t, v), IDENTITY(FL_TYPEVALUES8(__VA_ARGS__))

#define FL_VALUES_0()
#define FL_VALUES_2(t, v) v
#define FL_VALUES_4(t, v, ...)           FL_VALUES_2(t, v), FL_VALUES_2(__VA_ARGS__)
#define FL_VALUES_6(t, v, ...)           FL_VALUES_2(t, v), FL_VALUES_4(__VA_ARGS__)
#define FL_VALUES_8(t, v, ...)           FL_VALUES_2(t, v), FL_VALUES_6(__VA_ARGS__)
#define FL_VALUES_10(t, v, ...)          FL_VALUES_2(t, v), FL_VALUES_8(__VA_ARGS__)
#define FL_VALUES_12(t, v, ...)          FL_VALUES_2(t, v), FL_VALUES_10(__VA_ARGS__)  
  
#define FL_TYPEVALUES__(count, ...)      IDENTITY(FL_CONCAT(FL_TYPEVALUES, count)(__VA_ARGS__))
#define FL_TYPEVALUES_(count, ...)       FL_TYPEVALUES__(count, __VA_ARGS__)
#define FL_TYPEVALUES(...)               FL_TYPEVALUES_(FL_TYPEVALUES_COUNT(__VA_ARGS__), __VA_ARGS__)
  
#define FL_VALUES__(count, ...)          FL_VALUES_##count(__VA_ARGS__)
#define FL_VALUES_(count, ...)           FL_VALUES__(count, __VA_ARGS__)
#define FL_VALUES(...)                   FL_VALUES_(FL_TYPEVALUES_COUNT(__VA_ARGS__), __VA_ARGS__)

template <typename T>
void PRINT_V(T name) {
  std::cout << name;
}
  
template <typename T>
void PRINT_V(T* name) {
  std::cout << *name;
}   
  
#define PRINT_ARGS2(t, v)                           \
  printf("input:%s %s= ",#v, #t);                   \
  PRINT_V(v);                                       \
  printf("\n");                                     \
  fflush(stdout);
 
#define PRINT_ARGS4(t, v, ...)           PRINT_ARGS2(t, v) PRINT_ARGS2(__VA_ARGS__)
#define PRINT_ARGS6(t, v, ...)           PRINT_ARGS2(t, v) PRINT_ARGS4(__VA_ARGS__)
#define PRINT_ARGS8(t, v, ...)           PRINT_ARGS2(t, v) PRINT_ARGS6(__VA_ARGS__)
#define PRINT_ARGS10(t, v, ...)          PRINT_ARGS2(t, v) PRINT_ARGS8(__VA_ARGS__)
#define PRINT_ARGS12(t, v, ...)          PRINT_ARGS2(t, v) PRINT_ARGS10(__VA_ARGS__)
  
#define PRINT_ARGS__(count, ...)         PRINT_ARGS##count(__VA_ARGS__)
#define PRINT_ARGS_(count, ...)          PRINT_ARGS__(count, __VA_ARGS__)
#define PRINT_ARGS(...)                  PRINT_ARGS_(FL_TYPEVALUES_COUNT(__VA_ARGS__), __VA_ARGS__)

#define PRINT_RET(t, v)                  printf("output:%s %s= ",#v, #t); PRINT_V(v); printf("\n"); fflush(stdout);
  
#define SDK_PROXY(t, name, ...)                       \
  t internal_##name(FL_TYPEVALUES(__VA_ARGS__));      \
  t name(FL_TYPEVALUES(__VA_ARGS__)) {                \
	PRINT_ARGS(__VA_ARGS__);                          \
    t ret = internal_##name(FL_VALUES(__VA_ARGS__));  \
	PRINT_RET(#t, ret);                               \
    return ret;                                       \
  }                                                   \
  t internal_##name(FL_TYPEVALUES(__VA_ARGS__))

struct StructA
{
	int     A;
	char    B;
	float   C;
	char*   D;
	int     E[4];
	friend std::ostream & operator<<(std::ostream &out, StructA &A)
	{
		out << "StructA["<<A.A <<","<< A.B<<","<<A.C<<","<<A.D<<",";
		std::for_each(std::begin(A.E),
			std::end(A.E),
			[](const int &e) {
				std::cout << e << ",";
			});
		out<<"]";
		return out;
	}	
};

struct StructB
{
	int      A[4];
	StructA  B;
	friend std::ostream & operator<<(std::ostream &out, StructB &A)
	{
		out << "StructB[";
		std::for_each(std::begin(A.A),
			std::end(A.A),
			[](const int &e) {
				std::cout << e << ",";
			});
		out<< A.B<<"]";
		return out;
	}
};

StructA user_api(StructA A,StructB* B);

SDK_PROXY(StructA, user_api,StructA,A,StructB*,B,int,C,float,D)
{
	StructA ret=A;
	ret.A+=100;	
    return ret;
}

int main(int argc,char*argv[])
{
	StructA A;
	StructB B;
	A.A=1;
	A.B='2';
	A.C=3.0;
	A.D="4";
	int array0[]={10,11,12,13};
	std::copy(std::begin(array0), std::end(array0), std::begin(A.E));
	
	B.B=A;
	int array1[]={26,27,28,29};
	std::copy(std::begin(array1), std::end(array1), std::begin(B.A));
	
	StructA ret=user_api(A,&B,1000,2000.2);
	return 0;
}