関数の戻り値が constexpr かどうかを判定する
そんな感じの constexpr 関数を書いてみました。
まさに誰得。
[ソース]
#include <type_traits> template<typename T> constexpr bool true_(T){ return true; } template<typename T, typename ...Args, bool = true_(T{}(Args{}...))> constexpr bool is_constexpr_impl(bool&&){ return true; } template<typename T, typename ...Args> constexpr bool is_constexpr_impl(bool const&&){ return false; } template<typename T, typename ...Args> constexpr bool is_constexpr(Args&&...){ return is_constexpr_impl<T, typename std::decay<Args>::type...>(0); } template< typename FuncType, typename std::add_pointer<FuncType>::type Func, typename ...Args, bool = true_(Func(Args{}...)) > constexpr bool is_constexpr_impl(bool&&){ return true; } template< typename FuncType, typename std::add_pointer<FuncType>::type Func, typename ...Args > constexpr bool is_constexpr_impl(bool const&&){ return false; } template< typename FuncType, typename std::add_pointer<FuncType>::type Func, typename ...Args > constexpr bool is_constexpr(Args...){ return is_constexpr_impl<FuncType, Func, Args...>(0); } struct X{ constexpr int operator ()() const{ return 0; } bool operator ()(int) const{ return 0; } constexpr float operator ()(float, float) const{ return 0; } }; constexpr int plus(int a, int b){ return a + b; } float minus(float a, float b){ return a - b; } #include <cmath> int main(){ // 関数オブジェクトの場合は、型をテンプレート引数に、引数型を関数引数に渡して評価 static_assert( is_constexpr<X>(), ""); static_assert(!is_constexpr<X>(0), ""); static_assert( is_constexpr<X>(0.0f, 0.0f), ""); // 関数の場合は、第一引数に関数型、第二引数に関数ポインタを渡す static_assert( is_constexpr<decltype(plus), &plus>(0, 0), ""); static_assert(!is_constexpr<decltype(minus), &minus>(0.0f, 0.0f), ""); // コンパイラ依存になりそうな関数とか static_assert(is_constexpr<decltype(sin), &sin>(0.0), ""); static_assert(is_constexpr<decltype(cos), &cos>(0.0), ""); static_assert(is_constexpr<decltype(tan), &tan>(0.0), ""); return 0; }
デフォルトテンプレート引数で関数を評価して、それで SFINAE しています。
とりあえず、gcc 4.7 では動いていますね。
コンパイラに依存しそうな constexpr 関数(math とか get とか forward とか)を切り替える場合に使える…かな?
あと引数型にデフォルトコンストラクタがない場合は動きません。
にょろーん。