2017-08-15 28 views
6

我正在它有一個模板功能使項目失敗編譯:使C++模板函數的具體實例

template <class T> 
T foo<T>(T val) { return someFunc(val); } 

template <> 
bool foo<bool>(bool val) { return otherFunc(val); }; 

現在,我有一個類Bar,我不想接受爲輸入。事實上,我想讓它產生一個容易發現的編譯錯誤。問題是,如果我這樣做:

template <> 
Bar foo<Bar>(Bar val) { static_assert(false,"uh oh..."); } 

它在每次編譯時失敗。我發現https://stackoverflow.com/a/3926854/7673414,它說我需要引用模板類型,否則靜態斷言總是會發生。問題是我在這裏沒有模板類型。如果我這樣做:

template< typename T > 
struct always_false { 
    enum { value = false }; 
}; 

template <> 
Bar foo<Bar>(Bar val) { static_assert(always_false<Bar>::value,"uh oh..."); } 

那麼它也總是編譯失敗。有沒有辦法確保類型爲Bar的模板實例化總是會導致編譯錯誤?

回答

18

由於foo是一個完整的專業化,它總是會被編譯,靜態斷言總是會被調用。

然而,有一個easier way

template <> 
Bar foo<Bar>(Bar val) = delete; 

這會說這個特定的版本將被刪除,而且不能被調用。

+0

這很好,但我會刪除d-tor,而不必刪除所有各種c-tor。 –

+1

@YehezkelB。這是一個函數模板,而不是一個類模板。您可以刪除函數模板特化,而不僅僅是構造函數和析構函數。 –

2

您可以使用std::is_same來滿足您的要求。

template <class T> 
T foo<T>(T val) 
{ 
    // Make sure T is not Bar 
    static_assert(std::is_same<T, Bar>::value == false, "uh oh..."); 
    return someFunc(val); 
} 
+1

請您添加缺少')''爲static_assert'? –

+0

@風王,完成。感謝您指出。 –

3

另一種方法是使模板(不專業版),只有當類型是不同的,從Bar

template <class T> 
typename std::enable_if< ! std::is_same<T, Bar>::value, T>::type foo<T>(T val) 
{ return someFunc(val); } 

如果你可以使用C++ 14時,可以使用簡化std::enable_if_t

template <class T> 
std::enable_if_t< ! std::is_same<T, Bar>::value, T> foo<T>(T val) 
{ return someFunc(val); } 
1

如果您使用的是C++ 17,您可以將所有內容放在一起:constexpr if

template< typename T > 
auto foo(T val) 
{ 
    static_assert(!std::is_same_v<T,Bar>); 

    if constexpr(std::is_same_v<T,bool>) 
    { 
     return other_func(val); 
    } 
    else 
    { 
     return some_func(val); 
    } 

} 

然後你可以在static_assert的第一行,沒有模板特定實例編譯失敗的痛苦。

一個活生生的例子,請https://wandbox.org/permlink/PpR6G0gcvMRoxhhZ