函数模板的别名
alias of a function template
我创建了一个 CPU 调度程序,它可以将具有不同编译选项的相同函数编译到不同的目标文件中。为了让我的代码访问不同目标文件中的相同函数,我需要为每个目标文件中的函数指定不同的名称。
在 C(或 C++)中,我会在函数声明的头文件中做类似的事情。
typedef float MyFuncType(float a);
MyFuncType myfunc_SSE2, myfunc_SSE41, myfunc_AVX, myfunc_AVX2, myfunc_AVX512
但现在我想要声明的函数模板。我的真实代码目前看起来更像这样
//kernel.h
template <typename TYPE, unsigned N, typename VALUES>
void foo_SSE2(int32_t *buffer, VALUES & v);
template <typename TYPE, unsigned N, typename VALUES>
void foo_SSE41(int32_t *buffer, VALUES & v);
...
template <typename TYPE, unsigned N, typename VALUES>
void foo_AVX512(int32_t *buffer, VALUES & v);
#if INSTRSET == 2 // SSE2
#define FUNCNAME foo_SSE2
#elif INSTRSET == 5 // SSE4.1
#define FUNCNAME foo_SSE41
...
#if INSTRSET == 9 // AVX512
#define FUNCNAME foo_AVX512
#endif
这些只是头文件中的声明。函数定义位于单独的源文件中,该文件针对每个函数名称编译为不同的目标文件。定义看起来像这样
//kernel.cpp
#include "kernel.h"
template<typename TYPE, unsigned N, typename VALUES>
void FUNCNAME(int32_t *buffer, VALUES & v) {
//code
}
然后我这样编译
gcc -c -O3 -msse2 kernel.cpp -o kernel_sse2.o
gcc -c -O3 -msse4.1 kernel.cpp -o kernel_sse41.o
...
gcc -c -O3 -mavx512f kernel.cpp -o kernel_avx512.o
gcc -O3 main.cpp kernel_sse2.o kernel_sse41.o ... kernel_avx512.o
文件main.cpp
是另一个源文件,它只需要知道函数声明,这样linker就可以link它们到其他目标文件中的定义。看起来像这样
void dispatch(void) {
int iset = instrset_detect();
if (iset >= 9) {
fp_float1 = &foo_AVX512<float,1>;
}
else if (iset >= 8) {
fp_float1 = &foo_AVX2<float,1>;
}
...
else if (iset >= 2) {
fp_float1 = &foo_SSE2<float,1>;
}
}
int main(void) {
dispatch();
fp_float1(buffer, values);
}
但在我的文件 "kernel.h" 中,对函数名称的每次更改都重复此操作很烦人(而且容易出错)。我想要类似下面的东西(我知道这是行不通的)。
template <typename TYPE, unsigned N, typename VALUES>
typedef void foo(int32_t *buffer, VALUES & v);
foo foo_SSE2, foo_SSE41, foo_SSE_AVX, foo_AVX2, foo_AVX512
有没有一种理想的方法可以将声明和定义分开并允许我简单地重命名相同的模板函数声明?
这似乎是预处理器的应用程序:
#define EMIT_FUNCTION_PROTOTYPE(func_name, func_suffix) \
template<typename TYPE, unsigned N, typename VALUES> \
void func_name ## func_suffix (int32_t *buffer, VALUES & v)
#define EMIT_FUNCTION_PROTOTYPES(func_name) \
EMIT_FUNCTION_PROTOTYPE(func_name, _SSE2); \
EMIT_FUNCTION_PROTOTYPE(func_name, _SSE41); \
EMIT_FUNCTION_PROTOTYPE(func_name, _AVX); \
EMIT_FUNCTION_PROTOTYPE(func_name, _AVX2); \
EMIT_FUNCTION_PROTOTYPE(func_name, _AVX512)
然后只需一行就可以生成头文件中的所有原型:
EMIT_FUNCTION_PROTOTYPES(foo);
// expands to:
// template <typename TYPE, unsigned N, typename VALUES>
// void foo_SSE2(int32_t *buffer, VALUES & v);
//
// template <typename TYPE, unsigned N, typename VALUES>
// void foo_SSE41(int32_t *buffer, VALUES & v);
//
// template <typename TYPE, unsigned N, typename VALUES>
// void foo_AVX(int32_t *buffer, VALUES & v);
//
// template <typename TYPE, unsigned N, typename VALUES>
// void foo_AVX2(int32_t *buffer, VALUES & v);
//
// template <typename TYPE, unsigned N, typename VALUES>
// void foo_AVX512(int32_t *buffer, VALUES & v);
我认为这不是一个很大的好处,但它应该能满足您的需求。
我创建了一个 CPU 调度程序,它可以将具有不同编译选项的相同函数编译到不同的目标文件中。为了让我的代码访问不同目标文件中的相同函数,我需要为每个目标文件中的函数指定不同的名称。
在 C(或 C++)中,我会在函数声明的头文件中做类似的事情。
typedef float MyFuncType(float a);
MyFuncType myfunc_SSE2, myfunc_SSE41, myfunc_AVX, myfunc_AVX2, myfunc_AVX512
但现在我想要声明的函数模板。我的真实代码目前看起来更像这样
//kernel.h
template <typename TYPE, unsigned N, typename VALUES>
void foo_SSE2(int32_t *buffer, VALUES & v);
template <typename TYPE, unsigned N, typename VALUES>
void foo_SSE41(int32_t *buffer, VALUES & v);
...
template <typename TYPE, unsigned N, typename VALUES>
void foo_AVX512(int32_t *buffer, VALUES & v);
#if INSTRSET == 2 // SSE2
#define FUNCNAME foo_SSE2
#elif INSTRSET == 5 // SSE4.1
#define FUNCNAME foo_SSE41
...
#if INSTRSET == 9 // AVX512
#define FUNCNAME foo_AVX512
#endif
这些只是头文件中的声明。函数定义位于单独的源文件中,该文件针对每个函数名称编译为不同的目标文件。定义看起来像这样
//kernel.cpp
#include "kernel.h"
template<typename TYPE, unsigned N, typename VALUES>
void FUNCNAME(int32_t *buffer, VALUES & v) {
//code
}
然后我这样编译
gcc -c -O3 -msse2 kernel.cpp -o kernel_sse2.o
gcc -c -O3 -msse4.1 kernel.cpp -o kernel_sse41.o
...
gcc -c -O3 -mavx512f kernel.cpp -o kernel_avx512.o
gcc -O3 main.cpp kernel_sse2.o kernel_sse41.o ... kernel_avx512.o
文件main.cpp
是另一个源文件,它只需要知道函数声明,这样linker就可以link它们到其他目标文件中的定义。看起来像这样
void dispatch(void) {
int iset = instrset_detect();
if (iset >= 9) {
fp_float1 = &foo_AVX512<float,1>;
}
else if (iset >= 8) {
fp_float1 = &foo_AVX2<float,1>;
}
...
else if (iset >= 2) {
fp_float1 = &foo_SSE2<float,1>;
}
}
int main(void) {
dispatch();
fp_float1(buffer, values);
}
但在我的文件 "kernel.h" 中,对函数名称的每次更改都重复此操作很烦人(而且容易出错)。我想要类似下面的东西(我知道这是行不通的)。
template <typename TYPE, unsigned N, typename VALUES>
typedef void foo(int32_t *buffer, VALUES & v);
foo foo_SSE2, foo_SSE41, foo_SSE_AVX, foo_AVX2, foo_AVX512
有没有一种理想的方法可以将声明和定义分开并允许我简单地重命名相同的模板函数声明?
这似乎是预处理器的应用程序:
#define EMIT_FUNCTION_PROTOTYPE(func_name, func_suffix) \
template<typename TYPE, unsigned N, typename VALUES> \
void func_name ## func_suffix (int32_t *buffer, VALUES & v)
#define EMIT_FUNCTION_PROTOTYPES(func_name) \
EMIT_FUNCTION_PROTOTYPE(func_name, _SSE2); \
EMIT_FUNCTION_PROTOTYPE(func_name, _SSE41); \
EMIT_FUNCTION_PROTOTYPE(func_name, _AVX); \
EMIT_FUNCTION_PROTOTYPE(func_name, _AVX2); \
EMIT_FUNCTION_PROTOTYPE(func_name, _AVX512)
然后只需一行就可以生成头文件中的所有原型:
EMIT_FUNCTION_PROTOTYPES(foo);
// expands to:
// template <typename TYPE, unsigned N, typename VALUES>
// void foo_SSE2(int32_t *buffer, VALUES & v);
//
// template <typename TYPE, unsigned N, typename VALUES>
// void foo_SSE41(int32_t *buffer, VALUES & v);
//
// template <typename TYPE, unsigned N, typename VALUES>
// void foo_AVX(int32_t *buffer, VALUES & v);
//
// template <typename TYPE, unsigned N, typename VALUES>
// void foo_AVX2(int32_t *buffer, VALUES & v);
//
// template <typename TYPE, unsigned N, typename VALUES>
// void foo_AVX512(int32_t *buffer, VALUES & v);
我认为这不是一个很大的好处,但它应该能满足您的需求。