功能模板的别名 [英] alias of a function template

查看:51
本文介绍了功能模板的别名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个CPU调度程序,它将具有不同编译选项的相同功能编译为不同的目标文件。为了使我的代码能够访问不同目标文件中的相同函数,我需要为每个目标文件中的函数赋予不同的名称。



在C(或C ++)中,我会在头文件中为函数的声明做类似的事情。

  typedef float MyFuncType(float a); 

MyFuncType myfunc_SSE2,myfunc_SSE41,myfunc_AVX,myfunc_AVX2,myfunc_AVX512

但是现在我想要用于声明的函数模板。我的真实代码目前看起来更像这样

  // kernel.h 
template< typename TYPE,无符号N,类型名称VALUES>
void foo_SSE2(int32_t * buffer,VALUES& v);

模板< typename TYPE,无符号N,typename VALUES>
void foo_SSE41(int32_t * buffer,VALUES& v);
...
模板< typename TYPE,unsigned N,typename VALUES>
void foo_AVX512(int32_t * buffer,VALUES& v);

#if INSTRSET == 2 // SSE2
#定义功能名称foo_SSE2
#elif INSTRSET == 5 // SSE4.1
#定义功能名称foo_SSE41
...
#if INSTRSET == 9 // AVX512
#定义功能名称foo_AVX512
#endif

这些只是头文件中的声明。函数定义在单独的源文件中,该源文件针对每个函数名称编译为不同的目标文件。定义看起来像这样

  // kernel.cpp 
#include kernel.h
template< typename TYPE,无符号N,typename VALUES>
void FUNCNAME(int32_t * buffer,VALUES& v){
//代码
}

然后我像这样编译

  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 是另一个源文件,只需要知道函数声明,链接器就可以将它们链接到其他目标文件中的定义。看起来像这样

  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(缓冲区,值);
}

但是在我的文件 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
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); 
//扩展为:
//模板< typename TYPE,无符号N,typename VALUES>
// void foo_SSE2(int32_t * buffer,VALUES& v);
//
//模板< typename TYPE,unsigned N,typename VALUES>
// void foo_SSE41(int32_t * buffer,VALUES& v);
//
//模板< typename TYPE,unsigned N,typename VALUES>
// void foo_AVX(int32_t * buffer,VALUES& v);
//
//模板< typename TYPE,unsigned N,typename VALUES>
// void foo_AVX2(int32_t * buffer,VALUES& v);
//
//模板< typename TYPE,unsigned N,typename VALUES>
// void foo_AVX512(int32_t * buffer,VALUES& v);

我认为这不是一个巨大的好处,但它应该可以为您提供想要的东西。 / p>

I have created a CPU dispatcher which compiles the same functions with different compile options into different object files. In order for my code to access the same functions in different object files I need to give the functions in each object file a different name.

In C (or C++) I would do something like this in the header file for the declarations of the function.

typedef float MyFuncType(float a);

MyFuncType  myfunc_SSE2, myfunc_SSE41, myfunc_AVX, myfunc_AVX2, myfunc_AVX512

But now I want function templates for the declarations. My real code currently looks more like this

//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

These are only declarations in a header file. The function definitions are in a separate source file which is compiled to a different object file for each function name. The definitions look something like this

//kernel.cpp
#include "kernel.h"
template<typename TYPE, unsigned N, typename VALUES>
void FUNCNAME(int32_t *buffer, VALUES & v) {
    //code
}

Then I compile like this

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

The file main.cpp is another source file which only needs to know the function declarations so that the linker can link them to the definitions in the other object files. It looks like this

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);
}

But in my file "kernel.h" it's annoying (and error prone) to repeat this for every change in function name. I want something like the following (which I know does not work).

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

Is there an ideal way to to this which separates the declarations and definitions and allows me to simply rename identical template function declarations?

解决方案

This seems like an application for the preprocessor:

#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)

Then it's just a one-liner to generate all of the prototypes in your header file:

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);

I don't think this is a huge benefit, but it should give you what you want.

这篇关于功能模板的别名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆