5 回答

TA貢獻(xiàn)1911條經(jīng)驗(yàn) 獲得超7個(gè)贊
是的,使用SFINAE,您可以檢查給定的類是否提供某種方法。這是工作代碼:
#include <iostream>struct Hello{ int helloworld() { return 0; }};struct Generic {}; // SFINAE testtemplate <typename T>class has_helloworld{ typedef char one; typedef long two; template <typename C> static one test( typeof(&C::helloworld) ) ; template <typename C> static two test(...); public: enum { value = sizeof(test<T>(0)) == sizeof(char) };};int main(int argc, char *argv[]){ std::cout << has_helloworld<Hello>::value << std::endl; std::cout << has_helloworld<Generic>::value << std::endl; return 0;}
我剛用Linux和gcc 4.1 / 4.3測試過它。我不知道它是否可以移植到運(yùn)行不同編譯器的其他平臺

TA貢獻(xiàn)1878條經(jīng)驗(yàn) 獲得超4個(gè)贊
這個(gè)問題很老,但是使用C ++ 11,我們有了一種新方法來檢查函數(shù)是否存在(或者確實(shí)存在任何非類型成員),再次依賴SFINAE:
template<class T>auto serialize_imp(std::ostream& os, T const& obj, int) -> decltype(os << obj, void()){ os << obj;}template<class T>auto serialize_imp(std::ostream& os, T const& obj, long) -> decltype(obj.stream(os), void()){ obj.stream(os);}template<class T>auto serialize(std::ostream& os, T const& obj) -> decltype(serialize_imp(os, obj, 0), void()){ serialize_imp(os, obj, 0);}
現(xiàn)在進(jìn)行一些解釋。首先,如果內(nèi)部的第一個(gè)表達(dá)式無效(也就是說,函數(shù)不存在),我使用表達(dá)式SFINAEserialize(_imp)
從重載解析中排除函數(shù)decltype
。
本void()
是用來做的所有這些函數(shù)的返回類型void
。
如果兩者都可用,則該0
參數(shù)用于優(yōu)先選擇重載os << obj
(文字0
是類型的int
,因此第一個(gè)重載是更好的匹配)。
現(xiàn)在,您可能需要一個(gè)特征來檢查函數(shù)是否存在。幸運(yùn)的是,寫起來很容易。但是請注意,您需要為自己想要的每個(gè)不同的函數(shù)名自己編寫一個(gè)特征。
#include <type_traits>template<class>struct sfinae_true : std::true_type{};namespace detail{ template<class T, class A0> static auto test_stream(int) -> sfinae_true<decltype(std::declval<T>().stream(std::declval<A0>()))>; template<class, class A0> static auto test_stream(long) -> std::false_type;} // detail::template<class T, class Arg>struct has_stream : decltype(detail::test_stream<T, Arg>(0)){};
并解釋。首先,sfinae_true
是一個(gè)幫助器類型,它基本上與寫入相同decltype(void(std::declval<T>().stream(a0)), std::true_type{})
。優(yōu)點(diǎn)是它更短。
接下來,取決于簽入是否失敗,struct has_stream : decltype(...)
從任一端std::true_type
或std::false_type
最后繼承。 最后,為您提供所傳遞的任何類型的“值”,而無需您知道如何構(gòu)建它。請注意,這只能在未評估的上下文中使用,例如,和其他。decltype
test_stream
std::declval
decltype
sizeof
請注意,decltype
不一定需要,因?yàn)?code>sizeof(并且所有未評估的上下文)都獲得了增強(qiáng)。它只是decltype
已經(jīng)提供了一種類型,因此只是更清潔。這是一個(gè)sizeof
重載的版本:
template<class T>void serialize_imp(std::ostream& os, T const& obj, int, int(*)[sizeof((os << obj),0)] = 0){ os << obj;}
由于同樣的原因,int
和long
參數(shù)仍然存在。數(shù)組指針用于提供sizeof
可以使用的上下文。

TA貢獻(xiàn)1799條經(jīng)驗(yàn) 獲得超8個(gè)贊
雖然這個(gè)問題已經(jīng)有兩年了,但我還是敢補(bǔ)充一下。希望它能澄清以前無可爭議的優(yōu)秀解決方案。我采用了Nicola Bonelli和Johannes Schaub的非常有用的答案,并將它們合并為一個(gè)解決方案,即恕我直言,更易讀,更清晰,不需要typeof
擴(kuò)展:
template <class Type>class TypeHasToString{ // This type won't compile if the second template parameter isn't of type T, // so I can put a function pointer type in the first parameter and the function // itself in the second thus checking that the function has a specific signature. template <typename T, T> struct TypeCheck; typedef char Yes; typedef long No; // A helper struct to hold the declaration of the function pointer. // Change it if the function signature changes. template <typename T> struct ToString { typedef void (T::*fptr)(); }; template <typename T> static Yes HasToString(TypeCheck< typename ToString<T>::fptr, &T::toString >*); template <typename T> static No HasToString(...);public: static bool const value = (sizeof(HasToString<Type>(0)) == sizeof(Yes));};
我用gcc 4.1.2檢查了它。這個(gè)功勞主要?dú)w功于Nicola Bonelli和Johannes Schaub,如果我的回答可以幫助你,請給他們一個(gè)投票:)
- 5 回答
- 0 關(guān)注
- 691 瀏覽
添加回答
舉報(bào)