2008-07-17

プリプロセッサメタプログラミング ファイルイテレーション

さて、インデントを保つにはどうすれば良いのか。それには、ファイルイテレーションと呼ばれている方法を用いるのだが、いやはや、なんとも解説しがたいコードではある。

#if !BOOST_PP_IS_ITERATING

#ifndef HITO_FUNCTION_TRAITS
#define HITO_FUNCTION_TRAITS

#ifndef FUNCTION_MAX_ARITY
#define FUNCTION_MAX_ARITY   15
#endif // #ifndef FUNCTION_MAX_ARITY

#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>

// Primary Template class
template < typename Signature >
struct function_traits ;

#define BOOST_PP_ITERATION_PARAMS_1   (3, (0, FUNCTION_MAX_ARITY, "function_traits.hpp"))
#include BOOST_PP_ITERATE()




#endif //#ifndef HITO_FUNCTION_TRAITS

#elif BOOST_PP_ITERATION_DEPTH() == 1 // #if !BOOST_PP_IS_ITERATING

#define n BOOST_PP_ITERATION()

template < typename R BOOST_PP_ENUM_TRAILING_PARAMS(n, typename T) >
struct function_traits< R( BOOST_PP_ENUM_PARAMS(n, T) ) >
{
    typedef R return_type ;
    static int const number_of_aritys = n ;
#if n != 0
#define BOOST_PP_ITERATION_PARAMS_2   (3, (0, n-1, "function_traits.hpp"))
#include BOOST_PP_ITERATE()
#endif
    
} ;

#undef n

#elif BOOST_PP_ITERATION_DEPTH() == 2 // #if !BOOST_PP_IS_ITERATING

#define n BOOST_PP_ITERATION()
typedef BOOST_PP_CAT(T, n) BOOST_PP_CAT(Arg, n) ;
#undef n

#endif // #if !BOOST_PP_IS_ITERATING

しかし、ためしにVCのコンパイラにプリプロセスさせてみると、恐ろしく大量の改行を吐く。これでは意味がない。試みに、前回のコードを多少手直ししてみると。

#ifndef HITO_FUNCTION_TRAITS
#define HITO_FUNCTION_TRAITS

#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>

#ifndef FUNCTION_MAX_ARITY
#define FUNCTION_MAX_ARITY 15
#endif // #ifndef FUNCTION_MAX_ARITY

template < typename Signature >
struct function_traits ;

#define HITO_arg_typedef(z, n, unused)                 \
typedef BOOST_PP_CAT(T, n) BOOST_PP_CAT(Arg, n) ;

#define HITO_function_traits(z, n, unused)               \
template < typename R BOOST_PP_ENUM_TRAILING_PARAMS(n, typename T) >  \
struct function_traits< R ( BOOST_PP_ENUM_PARAMS(n, T) ) >       \
{                                    \
    typedef R return_type ;                     \
    static int const number_of_aritys = n ;             \
    BOOST_PP_REPEAT(n, HITO_function_typedef, ~)          \
} ;

BOOST_PP_REPEAT(FUNCTION_MAX_ARITY, HITO_function_traits, ~)

#undef HITO_function_traits
#undef HITO_arg_typedef

#endif //#ifndef HITO_FUNCTION_TRAITS

こちらの方が分かりやすい。何しろ、Boostの素晴らしいプリプロセッサライブラリのおかげで、リピートのネストというものを意識しないでいい。コンパイル速度向上の点から言えば、実はマクロのz引数を利用したほうがいいのだが、最近のハードウェアはだいぶ早いし、特に意識する必要も無い。

2 comments:

Anonymous said...

もう変態すぎて私には理解できませんw
本当に、Boostには色々なものがあるものですね! 感動しました。

江添亮 said...

変態というより、力技です。