2012-08-17 72 views
6

我有下面的代碼不能編譯。 這是一個模板類,它的參數模板方法enable_if專業化

typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { 
    // ... 
} 

typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { 
    // .... 
} 

我想有根據懲戒是什麼類型的成員方法的專業化兩種功能。

有沒有人有一些想法?

回答

7

SFINAE不適用於非模板函數(成員或非成員)。

正如Kerrek SB指出的那樣,使它們成爲非成員函數模板將起作用。或者Xeo指出,使用默認的模板參數使它們成員函數模板也可以工作。

然而,這僅僅是工作,因爲在兩個std::enable_if條件非重疊。如果你想爲int添加一個不同的過載(比如說),那麼你會發現它不能很好地縮放。根據你想要做什麼,標籤調度一般鱗比SFINAE與要派在多個備選方案更好:

#include<type_traits> 

template<typename Ret> 
class Foo 
{ 
public: 
    void _on_dispatched() 
    { 
     // tag dispachting: create dummy of either std::false_type or std::true_type 
     // almost guaranteed to be optimized away by a decent compiler 
     helper_on_dispatched(std::is_void<Ret>()); 
    } 

private: 
    void helper_on_dispatched(std::false_type) 
    { 
     // do stuff for non-void 
    } 

    void helper_on_dispatched(std::true_type) 
    { 
     // do stuff for void 
    } 
}; 

int main() 
{ 
    Foo<void>()._on_dispatched(); 
    Foo<int>()._on_dispatched(); 
    return 0; 
} 
+1

你可以,如果重載之一是在調用時是唯一可行的。 :) http://liveworkspace.org/code/fd6e5383610d4e0d8fb17c5497991355 – Xeo 2012-08-17 08:46:38

+1

@Patatoswatter:其實,不,這不是一個笑話。看到鏈接,你完全可以擁有一個完全相同的簽名功能,只有返回類型決定它是否可行。 :P另外,只需使用'std :: is_void ()',類型特徵就需要從'std :: true_type'或'std :: false_type'派生。 – Xeo 2012-08-17 09:08:53

+1

順便說一句,[你可以使用C++ 11中的默認參數使成員函數成爲模板](http://liveworkspace.org/code/781d94df5499998947217970c1aebf2a)。 – Xeo 2012-08-17 09:15:36

3

SFINAE僅適用於模板。您的代碼可以由具有一個小的修改編譯:

template <typename Ret> 
typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } 

template <typename Ret> 
typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } 

用法:

auto q = _on_dispatched<int>(); 

您當然不會演繹出函數的返回類型,因爲它不是推斷出。但是,可以包裏面這個模板另一個模板:

template <typename T> 
struct Foo 
{ 
    // insert templates here, maybe privately so 

    T bar() { return _on_dispatched<T>(); } 
}; 
+0

'template '爲成員函數,請參閱我對rhalbersma答案的評論。 – Xeo 2012-08-17 09:16:10

+0

@Xeo:你的意思是說我們不必寫''?當然,爲什麼不呢:-) – 2012-08-17 09:21:50