enable_if
関数をオーバーロードし (特殊化しない) 、オーバーロードのいずれかのみを選択的に有効にするために使用することで、目的の結果を得ることができます。
template<size_t D> typename std::enable_if<D!=0, double>::type my_func(...){}
template<size_t D> typename std::enable_if<D==0, double>::type my_func(...){}
enable_if
制約とは、D!=0
最初のオーバーロードのみが実行可能な関数でありD==0
、2 番目のオーバーロードのみが実行可能な関数であることを意味します。
C++03 では、 で同じことができますboost::enable_if_c
。
私の好ましい解決策は、醜いenable_if
使用法をカスタム特性タイプに置き換えることです。おそらく次のようなものです。
template<size_t> struct if_zero { typedef double disable; };
template<> struct if_zero<0> { typedef double enable; };
template<size_t D> typename if_zero<D>::disable my_func(...){}
template<size_t D> typename if_zero<D>::enable my_func(...){}
これは同じ効果がありますが、よりリテラシーなプログラミングスタイルになります。
さらに読みやすい別のフォームは次のとおりです。
template<bool, typename T> struct If_ { typedef T enable; };
template<typename T> struct If_<false, T> { };
template<bool B, typename T> using If = typename If_<B, T>::enable;
template<size_t D> If<D!=0, double> my_func(...){}
template<size_t D> If<D==0, double> my_func(...){}
「Concepts Lite」の提案では、次のように 2 番目のオーバーロードを制約することで、はるかにクリーンな方法でこれが可能になると思います。
template<size_t D> double my_func(...){}
template<size_t D> requires (D == 0)
double my_func(...){}
D==0
ここで、2 番目のオーバーロードは、最初のオーバーロードよりも制約が厳しいため、次の場合にのみ呼び出すことができ、オーバーロードの解決によって選択されます。