2017-10-08 113 views
2

我試圖實現一種機制來檢測提供的類是否包含一些靜態方法。這是很簡單的代碼,但我不明白爲什麼decltype()如預期EnableIfHasFooMethod類的專業化不起作用:SFINAE檢測靜態方法

#include <iostream> 

struct A { 
    static int Foo() { return 0; } 
}; 

template <class T, class = void> 
struct EnableIfHasFooMethod {}; 

template <class T> 
struct EnableIfHasFooMethod<T, decltype(T::Foo)> { 
    typedef void type; 
}; 

template <class T, class = void> 
struct HasFooMethod { 
    static const bool value = false; 
}; 

template <class T> 
struct HasFooMethod<T, typename EnableIfHasFooMethod<T>::type> { 
    static const bool value = true; 
}; 

int main() { 
    std::cout << HasFooMethod<A>::value << std::endl; 
    return 0; 
} 

輸出爲0,但應該是1

回答

3

您忘記添加void()

template <class T> 
struct EnableIfHasFooMethod<T, decltype(T::Foo, void())> { /* ... */ }; 
// ...........................................^^^^^^^^ 

您需要在

// ........................vvvv 
template <class T, class = void> 
struct EnableIfHasFooMethod {}; 

符合第二類(void),因此您的decltype()必須返回void當且僅當(當且僅當)有一個Foo()T

你不能寫

decltype(T::Foo) 

,因爲在這種情況下,decltype()返回成員Foo(如果存在的話),可以不void的類型。

你不能寫

decltype(void()) 

,因爲在這種情況下,decltype()不斷void,但你要它當且僅當有一個Foo成員T

因此,解決辦法是

decltype(T::Foo , void()) 

so SFINAE can work,failed the substituti如果沒有Foo成員並且如果有Foo則返回void

+0

我忘了專業化應該是默認的模板參數。謝謝! – eXXXXXXXXXXX2

+0

只是愛逗號運算符 – quetzalcoatl

+0

@quetzalcoatl - 我也是這樣。 – max66