元编程
编译期执行的变成,类似宏定义和模板,再编译期需要展开实现
宏定义
#define ARG_COUNTX(…) A1X(VA_ARGS) #define A3X(x) x //使宏定义在同一级展开 #define A1X(…) A3X(A4X(VA_ARGS, 3, 2, 1, 0)) #define A4X(1, 2, 3, count, …) count
A4X最大3个元素计数的宏定义
代码语言:javascript复制typedef struct{int a;int b;int c;}A;
#define PREPARE_MACRO(x) x //必须要加,否则__VA_ARGS__展开找不到对应项
#define FIELD_RECORD_INIT() std::vector<size_t> m_FieldOffset;
#define OFFSET(TYPE,MEMBER) ((size_t)(&(((TYPE*)0)->MEMBER)))
#define POINT_OFFSET_1(TYPE,MEMBER,...) m_FieldOffset.emplace_back(OFFSET(TYPE,MEMBER));
#define POINT_OFFSET_2(TYPE,MEMBER,...) POINT_OFFSET_1(TYPE,MEMBER) PREPARE_MACRO(POINT_OFFSET_1(TYPE,__VA_ARGS__))
#define POINT_OFFSET_3(TYPE,MEMBER,...) POINT_OFFSET_1(TYPE,MEMBER) PREPARE_MACRO(POINT_OFFSET_2(TYPE,__VA_ARGS__))
#define REGISTER_OFFSET(TYPE,...) FIELD_RECORD_INIT() PREPARE_MACRO(POINT_OFFSET_3(TYPE,__VA_ARGS__))
REGISTER_OFFSET(A,a,b,c)//遍历A的成员地址
- for循环
宏定义循环可以通过,类似上面的宏递归展开方式实现
模板元编程
代码语言:javascript复制template <typename R, typename... T> //R返回值,T参数列表
class dllfunctor_stdcall {
public:
dllfunctor_stdcall(string dll, string function)
{
_f = (R(__stdcall *)(T...))DLLMap::getInstance().getProcAddress(dll, function.c_str());
}
R operator()(T... args) { return _f(args...); }
private:
R(__stdcall *_f)(T...);
};
模板T,可以对应多参数函数,可以强转函数类型
代码语言:javascript复制template <typename T>
void fun(const T& t){
cout << t << 'n';
}
template <typename T, typename ... Args>
void fun(const T& t, Args ... args){
cout << t << ',';
fun(args...);//递归解决(函数名相同,参数不同),利用模板推导机制,每次取出第一个,缩短参数包的大小。
}
参数展开,args…或者{args,…}
- for循环
template <int I, int Max, typename Func>
struct ForLoop {
static void run(Func func) {
func(I);
ForLoop<I 1, Max, Func>::run(func); // 递归调用
}
};
template <int Max, typename Func>
struct ForLoop<Max, Max, Func> {
static void run(Func func) {}
};
ForLoop<0, 10, [](int i)>::run([](int i){std::cout << i << std::endl;});
- if条件判断
if constexpr,常量表达式