2017-04-18 71 views
0

https://stackoverflow.com/a/31860104瞭解C++ 11的解決方案,用於檢查一個成員函數

#include <iostream> 
#include <string> 

template<class T> 
auto optionalToString(T* obj) 
-> decltype( obj->toString() ) 
{ 
    return  obj->toString(); 
} 
auto optionalToString(...) -> std::string 
{ 
    return "toString not defined"; 
} 

struct TA 
{ 
    std::string toString() const 
    { 
     return "Hello"; 
    } 
}; 

struct TB 
{ 
};  

問題的存在>由於提出的解決方案optionalToString,我怎麼可以用它來檢測TA具有的toString而TB沒有。

+0

這是很難明白你在問什麼 –

+0

@DavidHaim我改變了問題,希望現在你可以閱讀它。 – q0987

+0

「檢測」是什麼意思?在'if constexpr(...)'上下文中?當你想要一個字符串? – Caleth

回答

3

使用can_applythis code A液:

template<class T> 
using toString_result = decltype(std::declval<T>().toString()); 

template<class T> 
constexpr auto has_toString = can_apply<toString_result, T>::value; 

像這樣來使用:

struct TA 
{ 
    std::string toString() const 
    { 
     return "Hello"; 
    } 
}; 

struct TB 
{ 
}; 

int main() 
{ 
    std::cout << has_toString<TA> << '\n'; 
    std::cout << has_toString<TB> << '\n'; 
    return 0; 
} 

DEMO

+0

建議的解決方案看起來也很簡單。畢竟這些元代碼複雜化後,它看起來不是一個簡單的解決方案。 – q0987

+0

@ q0987這是一種可用於任何操作的通用解決方案。如果你想堅持你的,目的是檢測,爲什麼不返回一個布爾值? –

+0

我發現問題在哪裏。在線編譯器不會生成正確的結果,我認爲代碼不起作用。這是編譯器而不是代碼的問題。謝謝 – q0987

1

給出的解決方案讓您始終獲得任何對象的字符串。如果它有一個toString()成員函數,將使用此方法,否則使用默認字符串。用法示例,給出了上述:

TA a; 
TB b; 
std::cout << "a: " << optionalToString(&a) << '\n'; 
std::cout << "b: " << optionalToString(&b) << std::endl; 

但是,你不會得到一個布爾值ab是否具有toString()方法。如果你想要的話,你需要像O'Neil提出的解決方案。