2016-05-13 44 views
4

我有三個函數做幾乎同樣的事情,但是這個過程是有點不同根據參數類型:最好的辦法派遣的好模板函數

template<typename T> void Func1(const T *in, T *out) 
{ 
    static_assert(std::is_same<T, INT8>::value 
        || std::is_same<T, UINT8>::value 
        || std::is_same<T, INT16>::value 
        || std::is_same<T, UINT16>::value, ""); 
    //... 
} 

template<typename T> void Func2(const T *in, T *out) 
{ 
    static_assert(std::is_same<T, INT32>::value || std::is_same<T, UINT32>::value, ""); 
    //... 
} 

template<typename T> void Func3(const T *in, T *out) 
{ 
    static_assert(std::is_same<T, float>::value || std::is_same<T, double>::value, ""); 
    //... 
} 

但我不想用戶必須決定哪個函數調用,所以我嘗試自動執行。遺憾的是到目前爲止,(我是一個C++初學者),我所知道的唯一辦法是:

template<typename T> void Function(const T *in, T *out) 
{ 
    if (std::is_same<T, UINT8>::value 
     || std::is_same<T, UINT16>::value 
     || std::is_same<T, INT8>::value 
     || std::is_same<T, INT16>::value) 
    { 
     Func1(in, out); 
     return ; 
    } 

    if (std::is_same<T,INT32>::value || std::is_same<T,UINT32>::value) 
    { 
     Func2(in, out); 
     return ; 
    } 

    if (std::is_same<T,float>::value || std::is_same<T,float>:: double) 
    { 
     Func3(in, out); 
     return ; 
    } 
} 

我覺得這個解決方案完全醜,我想知道如果有什麼更好/更快/更優雅是可能的嗎?

+2

什麼是'unsigned float'和'unsigned double'? – WhiZTiM

+0

你可以使用C++ 11嗎? – Garf365

+0

@ Garf365:是的! – FiReTiTi

回答

5

如果使用C++ 11或更大,則可以使用type_traits(SFINAE):

template<typename T> 
typename std::enable_if<std::is_same<T, INT8>::value 
      || std::is_same<T, UINT8>::value 
      || std::is_same<T, INT16>::value 
      || std::is_same<T, UINT16>::value>::type Function(const T*in, T*out) 
{ 
    Func1(in, out); 
} 

template<typename T> 
typename std::enable_if<std::is_same<T, INT32>::value 
      || std::is_same<T, UINT32>::value >::type Function(const T*in, T*out) 
{ 
    Func2(in, out); 
} 

template<typename T> 
typename std::enable_if<std::is_same<T, float>::value 
      || std::is_same<T, double>::value >::type Function(const T*in, T*out) 
{ 
    Func3(in, out); 
} 

實施例:http://coliru.stacked-crooked.com/a/b4f000fa6ffa8f19

或者,如果不能使用C++ 11或更大,您可以使用超載而不是模板:

void Function(const UINT8 *int, UINT8 * out) 
{ 
    Func1(in, out); 
} 
... 
void Function(const UINT32 *int, UINT32 * out) 
{ 
    Func2(in, out); 
} 
... 

或者你可以使用template specialization,但是,在這種情況下,它不是真正相關的(我離開這裏,因爲它是在原廠l答案):

template<typename T> Function(const T *in, T *out); 

template<> void Function(const UINT8 *in, UINT8 * out) 
{ 
    Func1(in, out); 
} 

template<> void Function(const INT8 *in, INT8 * out) 
{ 
    Func1(in, out); 
} 

.... 
+1

而不是專業化,只是使用超載。但首選的方法是SFINAE對我來說。 – Jarod42

+0

@ Jarod42我將它添加到答案 – Garf365

+0

感謝您的回答。在你的解決方案中,我甚至不需要再調用Func *,我可以在函數內部複製代碼。唯一不能編譯的就是「:: type」,但是如果我刪除它的話。這是爲什麼? (我還沒有忘記添加type_traits。 – FiReTiTi

4

你可以編寫一個特徵來檢查一個類型是否出現在列表中。此版本使用C++ 17中的std::disjunction,但您可以從鏈接中複製粘貼實施。

template <typename F, typename... T> 
using is_one_of = std::disjunction<std::is_same<F, T>...>; 

然後用SFINAEstd::enable_if選擇過載(std::enable_if_t是C++ 14,使用typename std::enable_if<...>::type如果你堅持11)。

template<typename T> 
std::enable_if_t<is_one_of<T, uint8_t, int8_t, uint16_t, int16_t>::value> 
Func(const T *in, T *out) 
{ 
    std::cout << "1\n"; 
} 

template<typename T> 
std::enable_if_t<is_one_of<T, uint32_t, int32_t>::value> 
Func(const T *in, T *out) 
{ 
    std::cout << "2\n"; 
} 

template<typename T> 
std::enable_if_t<std::is_floating_point<T>::value> 
Func(const T *in, T *out) 
{ 
    std::cout << "3\n"; 
} 

注意,你甚至不需要Func1Func2Func3,你可以使不同Func重載做你的處理。

Live Demo

+0

感謝您的回答。 「is_one_of」會產生錯誤。我在google上找到了「is_any_of」,但沒有找到「is_one_of」。 – FiReTiTi

+0

@FiReTiTi什麼是錯誤? – TartanLlama

+0

對不起,我忘記了:無法解析標識符「is_one_of」。 – FiReTiTi