ある型の引数を持つメンバ関数を持っているかどうか調べるのってどう書くんだろう。調べてみよう。
— 凹 (@hecomi) June 9, 2012
そういえば最近、メタプログラムを書いていないので、書いてみることにした。ある関数、もしくはメンバー関数が、ある型の仮引数を持っているかどうかを調べるメタプログラムだ。
template < std::size_t I, typename T, typename TUPLE > struct has_parameter_type_impl { using type = std::integral_constant< bool, std::is_same<T, typename std::tuple_element< I, TUPLE >::type >::value || has_parameter_type_impl< I-1, T, TUPLE>::type::value > ; } ; template < typename T, typename TUPLE> struct has_parameter_type_impl< 0, T, TUPLE > { using type = std::integral_constant< bool, std::is_same<T, typename std::tuple_element< 0, TUPLE >::type >::value > ; } ; template < typename T, typename Func > struct has_parameter_type { } ; template < bool B, typename T, typename F > struct lazy_conditional : std::conditional< B, T, F >::type { } ; template < typename T, typename R, typename ... Types > struct has_parameter_type<T, R (Types...) > : lazy_conditional< sizeof...(Types) == 0 , std::conditional< std::is_same<T, void>::value, std::true_type, std::false_type > , has_parameter_type_impl< sizeof...(Types) - 1, T, std::tuple< Types... > > >::type { } ; template < typename T, typename R, typename ... Types > constexpr bool has_param_type( R && ( Types ... ) ) { return has_parameter_type<T, R( Types... )>::value ; } template < typename T, typename R, typename ... Types > constexpr bool has_param_type( R (*) ( Types ... ) ) { return has_parameter_type<T, R( Types... )>::value ; } template < typename T, typename R, typename C, typename ... Types > constexpr bool has_param_type( R (C::*) ( Types ... ) ) { return has_parameter_type<T, R( Types... )>::value ; }
使い方
struct X { void f( char, double ) { } } ; void f( int, char, short ) { } int main() { std::cout << has_param_type<int>( &f ) << std::endl ; // true std::cout << has_param_type<float>( &f ) << std::endl ; // false std::cout << has_param_type<double>( &X::f ) << std::endl ; // true }
残念ながら、メンバー関数をコンパイル時にイテレートする方法がないので、クラス型を与えただけで自動的にメンバー関数を総なめにして判別してくれるメタプログラムは書けない。
N3326: Sequential access to data members and base sub-objectsをメンバー関数にも適用した機能が待ち望まれる。
No comments:
Post a Comment