ブログ記事からの転載です。
そんな感じの 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 とか)を切り替える場合に使える…かな?
あと引数型にデフォルトコンストラクタがない場合は動きません。
にょろーん。
[コンパイラ]
- g++ (GCC) 4.7.0 20111210 (experimental)