2016-08-14 37 views
1

是否可以專門化enum上的模板函數?枚舉上的C++專用函數

我見過注意here模板函數可以被禁用,如果它不是一個枚舉,但這是可能的,但仍然允許其他類型?下面

我的例子顯示了專業化intfloatenum(它不會編譯,因爲它試圖超載enum版本,而不是專業的話)。我覺得我失去了一些明顯的東西。

請注意,我在找專門的任何枚舉,而不是僅僅(在本例中EAnEnum)命名一個

#include <iostream> 

enum class EAnEnum 
{ 
    Alpha, 
    Beta, 
}; 

template<typename T> 
void MyFunc(); 

template<> 
void MyFunc<int>() 
{ 
    std::cout << "Int" << std::endl; 
} 

template<> 
void MyFunc<float>() 
{ 
    std::cout << "Float" << std::endl; 
} 

// MyFunc<Enum> 
template<typename T> 
typename std::enable_if<std::is_enum<T>::value, void>::type MyFunc() 
{ 
    std::cout << "Enum" << std::endl; 
} 

int main() 
{ 
    MyFunc<EAnEnum>(); 
    return 0; 
} 
+0

您正試圖執行函數模板的部分特化。沒有這種東西 - 你可以做全面的專業化,或超載。一種可能的方法 - 將特定於枚舉的實現放入主模板中,或許使用'static_assert',該類型實際上是一個枚舉。 –

+1

你試圖解決什麼實際問題。不,不是這個問題,但你認爲答案是這種專業化的問題。 –

+1

在一般情況下,功能專業化並不是解決幾乎所有您嘗試解決的問題的最佳方法。總之,將會有更好的方式。解決方案最終變得脆弱和尷尬。描述真正的問題,以另一種方式解決問題。 – Yakk

回答

2

不能部分專業的功能,但可以使用標籤調度改爲
它遵循基於業務方案的問題最少,工作示例:

#include <iostream> 
#include<type_traits> 

enum class EAnEnum 
{ 
    Alpha, 
    Beta, 
}; 

template<typename> 
struct tag {}; 

void MyFunc(tag<int>) 
{ 
    std::cout << "Int" << std::endl; 
} 

void MyFunc(tag<float>) 
{ 
    std::cout << "Float" << std::endl; 
} 

void MyFunc(tag<EAnEnum>) 
{ 
    std::cout << "Enum" << std::endl; 
} 

template<typename T> 
void MyFunc() { 
    MyFunc(tag<std::decay_t<T>>{}); 
} 

int main() 
{ 
    MyFunc<EAnEnum>(); 
    return 0; 
} 

您可以輕鬆地添加一個參數包轉發到正確的MyFunc並仍然使用這種技術來解決您的問題。
當然,你現在可以專注於任何枚舉。
您也可以提供一個備用MyFunc爲:

template<typename T> 
void MyFunc(tag<T>) 
{ 
    std::cout << "Fallback" << std::endl; 
} 

如果你想爲所有可能的枚舉類型回退,你現在可以依靠SFINAE,這些都是不同的重載函數:

template<typename T> 
std::enable_if_t<std::is_enum<T>::value> 
MyFunc(tag<T>) 
{ 
    std::cout << "Fallback for enums only" << std::endl; 
} 

請注意,您不應該直接使用接受tag專業化的MyFunc作爲切入點的含義。
這些意思是內部功能。
使用替代通用的,如示例中所示。

+0

這是否仍然需要我明確說明我的枚舉的名稱,如'標籤)'? –

+0

@cz對於那些重載函數,如果需要的話,你現在可以在你的'fallbacks'上使用_sfinae_。讓我編輯這個問題來澄清這一點。 – skypjack

2

你不能部分地專門化一個函數模板,但是你可以讓它轉發到一個類模板。

因爲你的函數沒有參數這是特別容易:通過std::forward

#include <iostream> 
#include <type_traits> 

namespace impl { 
    using namespace std; 

    template< class Type, bool is_enum_ = is_enum<Type>::value > 
    struct Foo; 

    template< class Type > 
    struct Foo<Type, true> 
    { void func() { cout << "Enum" << endl; } }; 

    template<> 
    struct Foo<int> 
    { void func() { cout << "Int" << endl; } }; 

    template<> 
    struct Foo<float> 
    { void func() { cout << "Float" << endl; } }; 

} // namespace impl 

template< class Type > 
void foo() 
{ impl::Foo<Type>().func(); } 

auto main() 
    -> int 
{ 
    enum class An_enum 
    { 
     alpha, beta, 
    }; 

    foo<An_enum>(); 
    foo<int>(); 
    foo<float>(); 
    #ifdef TEST 
     foo<char>(); //! Doesn't compile. 
    #endif 
} 

帶參數,您可以使用「完美轉發」(這是不是所有的完美,真的,但通常不夠好) 。