2016-04-15 12 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は2倍のコードがあり、そのほとんどは無関係です。 – user673679

+0

SFINAEの概念は、過負荷も部分的な特殊化もできないため、可変テンプレートには意味がありません。 – Brian

答えて

2

すぐにバットを外してください。自分の浮動小数点検出メカニズムを手渡しするのではなく、std::is_floating_pointを使うことをお勧めします。さらに、::valueではなく、_vの接尾辞をC++の17として使用することができます。

SFINAE自体を変数テンプレートで使用することはあまり意味がありませんが、浮動小数点型がPiの値を取ることを許可するというソリューションを試すことで実現できます変数テンプレートをタイプstd::enable_if_t< std::is_floating_point<T>::value, T>に設定します。条件が満たされている場合は、もちろん推論タイプのみが使用されます。整数型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> EnableIfFloatingPoint<T>は、任意の型を推定していませんが、私はこのSFINAEを考えていないので、単純に、コンパイルに失敗します。

適切な解決策は、static_assertというメッセージを持つconstexprファンクションテンプレートを使用し、テンプレートが「正しい」タイプでインスタンス化されたことを確認することです。

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}; 
} 
関連する問題