2015-05-19 137 views
2

我已經創建了一個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是隻需要知道函數的聲明,以便鏈接可以將它們鏈接到定義另一個源文件在其他對象文件中。它看起來像這樣

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 

有沒有一種理想的方式來分離聲明和定義,並允許我簡單地重命名相同的模板函數聲明?

+1

您可以讓預處理器完成這項工作。 – Columbo

+0

您可以使用模板typedef(使用'')[Live Demo](https://ideone.com/v7wDhj)保存參數輸入。但不能在一行中聲明幾個模板函數:/ – Jarod42

+1

C++ 11具有'using'關鍵字用於模板別名 – ftynse

回答

1

這似乎是爲預處理器的應用程序:

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

我不認爲這是一個巨大的好處,但它應該給你你想要的。

+0

謝謝,這確實是一個改進。 –

+0

我剛剛測試了你的代碼。我工作很棒。我還有更多這樣的功能,所以這可以簡化很多。 –