2016-03-02 74 views
14

考慮下面的代碼:爲什麼void_t <>檢測方式不適用於gcc-4.9?

#include <iostream> 
#include <type_traits> 

struct Test { Test& operator++(); }; 
struct NoIncrement { }; 

template <typename...> using void_t = void; 

template <class, class=void_t<>> 
struct has_pre_increment_member : std::false_type { }; 

template <class T> 
struct has_pre_increment_member<T, void_t<decltype(++std::declval<T&>())>> 
    : public std::true_type { }; 

int main() { 
    std::cout << has_pre_increment_member<Test>::value << " "; 
    std::cout << has_pre_increment_member<NoIncrement>::value << std::endl; 
} 

隨着克++ 5及之後的版本(以及-std = C++ 14標誌,當然),該代碼輸出

1 0 

,它應。隨着G ++ 4.9版本(和-std = C++ 14標誌),但是,它輸出

1 1 

兩個要求使用相同的語言標準是,有啥這裏的問題?

+2

你使用的是4.9.0還是比它高?我已經看到4.9.0中的一些錯誤,如果你轉到4.9.2,那麼這些錯誤是固定的。 – NathanOliver

+0

4.9.3確切地說 –

+0

那麼這就是我所能貢獻的。如果它讓你跌倒得更好,它也可以在叮噹中奏效。 – NathanOliver

回答

16

這是作爲CWG Issue 1558的結果,現在被認爲是gcc中的錯誤(特別是64395 - 當前已修復)。這個問題背後的想法是,既然你不實際使用的模板參數在這裏:

template <typename...> using void_t = void; 

沒有替換故障無論你嘗試在傳遞什麼類型或表達式

值得慶幸的是,有一個簡單的解決方法,不涉及升級您的編譯器。我們可以重寫void_t實際使用它的參數包,從而觸發替換故障:

namespace void_details { 
    template <class... > 
    struct make_void { using type = void; }; 
} 

template <class... T> using void_t = typename void_details ::make_void<T...>::type; 

這會讓你的例子做跨所有版本的GCC我想正確的事情。

相關問題