2012-08-22 69 views
22

假設我有一個模板函數模板功能專業化。做這個的最好方式是什麼?C++ 11:</p> <pre><code>template<typename T> void f(T t) { ... } </code></pre> <p>,我想寫對於所有基本的整數類型專業化:對於整數類型

我的意思是:

template<typename I where is_integral<I>::value is true> 
void f(I i) 
{ 
    ... 
} 

和編譯器會選擇整數類型的第二個版本,以及其他一切的第一個版本?

+0

C++ 11中是否有模板專門化功能?我認爲在C++ 03中它只是超載。 –

+0

我一直在尋找類似的東西,但失敗了。我所能做的只是定義一個正常的模板,並在裏面檢查給定的參數是否爲整型 –

+3

@AlexanderChertov有C++ 03,但[它很複雜](http://www.gotw.ca /publications/mill17.htm)。這同樣適用於C++ 11。 – juanchopanza

回答

36

使用SFINAE

// For all types except integral types: 
template<typename T> 
typename std::enable_if<!std::is_integral<T>::value>::type f(T t) 
{ 
    // ... 
} 

// For integral types only: 
template<typename T> 
typename std::enable_if<std::is_integral<T>::value>::type f(T t) 
{ 
    // ... 
} 

注意,您必須包含完整的std::enable_if即使對於聲明也返回值。

+1

您已將函數的返回值從void更改爲其他值。如果原始函數返回一個類型呢?例如一個類X? 'template X f(T t)'?那麼它會怎樣? –

+0

@ AndrewTomazos-Fathomling,如果僅給出1個模板參數,則'std :: ebable_if :: type'爲void;或第二個模板參數。 – Lol4t0

+1

@ AndrewTomazos-Fathomling「std :: enable_if」的第二個模板參數默認爲「void」。這是你的回報類型。我保留默認值,但您可以將其更改爲您想要的任何返回類型。甚至可以讓整型返回不同於非整型的類型。 – David

11

使用C++ 11的std :: enable_if(http://en.cppreference.com/w/cpp/types/enable_if)可以用來做:

template<typename T, class = typename std::enable_if<std::is_integral<T>::value>::type> 
void f(T t) {...} 
+0

它是否是有效的代碼? – Andrey

+1

差不多,但他做錯了。 – David

+0

edited :)語法相當複雜! – arnoo

7

您可以使用一個輔助的模板,你可以專注是這樣的:

#include <string> 
#include <iostream> 
#include <type_traits> 

template <typename T, bool = std::is_integral<T>::value> 
struct Foo { 
     static void bar(const T& t) { std::cout << "generic: " << t << "\n"; } 
}; 
template <typename T> 
struct Foo<T, true> { 
     static void bar(const T& t) { std::cout << "integral: " << t << "\n"; } 
}; 

template <typename T> 
static void bar(const T& t) { 
     return Foo<T>::bar(t); 
} 

int main() { 
     std::string s = "string"; 
     bar(s); 
     int i = 42; 
     bar(i); 
     return 0; 
} 

輸出:

generic: string 
integral: 42 
+1

+1類模板委託,因爲它不僅允許顯式的,專業化,這也與Sutter&Alexandrescu編碼標準的第66條一致:「不要專門設計功能模板」。 – TemplateRex

+0

@rhalbersma我喜歡這個答案,但我不認爲你的推理是合理的。 。對於這個問題,使用函數模板專門化並不是一個實際的選擇。 – David

+0

問題本身要求「專業化」 – mitchnull

19

我會用重載決議。這使您不必使用總的SFINAE黑客。不幸的是,有很多地方你無法避免它,但幸運的是不是其中之一。

template<typename T> 
void f(T t) 
{ 
    f(t, std::is_integral<T>()); 
} 

template<typename T> 
void f(T t, std::true_type) 
{ 
    // ... 
} 

template<typename T> 
void f(T t, std::false_type) 
{ 
    // ... 
} 
相關問題