2016-04-15 105 views
0

我可以對模板變量使用enable_if(或者是否存在一些替代技術)。例如可變模板和std :: enable_if

typedef float Float; 
typedef double Double; 

template<class T> 
constexpr Bool IsFloat = std::is_same_v<T, Float>; 

template<class T> 
constexpr Bool IsDouble = std::is_same_v<T, Double>; 

template<class T> 
constexpr Bool IsFloatingPoint = IsFloat<T> || IsDouble<T>; 

template<class T> 
using EnableIfFloatingPoint = std::enable_if_t<IsFloatingPoint<T>>; 

template 
< 
    class T, 
    typename = EnableIfFloatingPoint<T> 
> 
constexpr T Pi = T(3.1415926535897932384626433832795); 

Visual Studio中給了我一個編譯器錯誤說「太少模板參數」當我嘗試使用Pi<float>,例如。

+0

有點困惑爲什麼你沒有在這篇文章中加入IsFloatingPoint。 – WhozCraig

+0

@WhozCraig因爲現在有兩倍的代碼,而且大部分代碼都是不相關的。 – user673679

+0

SFINAE的概念對變量模板沒有意義,因爲它們既不能過載也不能部分專用。 – Brian

回答

2

馬上我推薦使用std::is_floating_point而不是手動滾動您自己的浮點檢測機制。另外,從C++ 17開始,您將可以使用_v後綴代替::value

正如在一些評論中提到的那樣,在變量模板上使用SFINAE本身沒什麼意義,但是您可以通過嘗試來實現只允許浮點類型取值爲Pi的解決方案將變量模板設置爲std::enable_if_t< std::is_floating_point<T>::value, T>,如果條件滿足,這當然只有推導類型。

template<class T> 
using EnableIfFloatingPoint = std::enable_if_t<std::is_floating_point<T>::value, T>; 

template<class T> 
constexpr T Pi = EnableIfFloatingPoint<T>(3.1415926535897932384626433832795); 

Pi<T>對於整型T將只是無法編譯,因爲 EnableIfFloatingPoint<T>不會有任何類型的推斷,但我不會考慮這個SFINAE。

更好的解決方案是將constexpr函數模板與適當的static_assert消息驗證模板是否使用「正確」類型實例化。

template<class T> 
constexpr T Pi() 
{ 
    using is_fp = std::is_floating_point<T>; 
    static_assert(is_fp::value, "Pi must be instantiated with floating point types."); 
    return T{3.1415926535897932384626433832795}; 
} 
相關問題