2016-01-04 42 views
1

我嘗試使用下面的結構來檢查成員函數的基礎上this answer的存在,我以前有:誤差decltype模板,msvc2013

template <typename T, class = double> 
struct has_a : std::false_type {}; 

template <typename T> 
struct has_a<T, decltype(std::declval<T>().a())> : std::true_type {}; 

這工作得很好用gcc 4.9.2 ,但失敗msvc2013編譯:

錯誤C2228:左 '一個' 必須有類/結構/聯合類型是 'add_rvalue_reference < _Ty> ::型'

看起來(?)像這是一個編譯器錯誤,因爲declval明確應該在未評估的decltype表達式(see here)內工作。有沒有已知的解決方法?

+0

這依賴於[表達式SFINAE](http://stackoverflow.com/questions/12654067/what-is-expression-sfinae#12654277),但MSVC2013 [不支持它](https:// msdn。 microsoft.com/en-us/library/hh567368.aspx)(儘管我知道他們有一些SFINAE功能可以用於下一個版本)。 – TartanLlama

+0

@TartanLlama這就是我所擔心的。有沒有一個類似的習語不會打破視覺工作室? –

+0

@NicolasHolthaus [嘗試這個](http://rextester.com/BMCKE70673) –

回答

1

MSVC 2013的尾部返回類型解析器似乎比表達SFINAE體系更加完善,如果檢查者重構方式如下(following T.C's suggestion),它按預期工作在兩個msvc2013和gcc 4.9.2:

template <typename T> 
struct has_a_impl 
{ 
    template<typename U> 
    static auto test(U* p) -> decltype(p->a()); // checks function existence 
    template<typename U> 
    static auto test(...) -> std::false_type; 

    using type = typename std::is_floating_point<decltype(test<T>(0))>::type; // checks return type is some kind of floating point 
}; 

template <typename T> 
struct has_a : has_a_impl<T>::type {}; 

該語法的一個附加好處是返回類型檢查可以使用任何type_traits,因此您不必檢查單個類型的返回值(例如double)。