マクロの可変長引数に対しての all_of, any_of, none_of アルゴリズム


最近 Boost.PP をすごく使うことが多いので
使ってる中で、欲しかったアルゴリズムを作ってみました。


マクロは個人的にはキライな方なんですが
Boost.PP くらい突き抜けるとアリだな、と思います。

#define  PP_VA_ALL_OF( mac, ... )  \
  BOOST_PP_EQUAL(  \
    BOOST_PP_SEQ_SIZE(  \
      BOOST_PP_SEQ_FILTER( PP_DETAIL_ALGORITHM_EXPAND, _,  \
        BOOST_PP_SEQ_FOR_EACH( PP_DETAIL_ALGORITHM_APPLY, mac, BOOST_PP_VARIADIC_TO_SEQ( __VA_ARGS__ ) )  \
        )  \
      ),  \
      BOOST_PP_SEQ_SIZE( BOOST_PP_VARIADIC_TO_SEQ( __VA_ARGS__ ) )  \
    )

#define PP_VA_ANY_OF( mac, ... )  \
  BOOST_PP_BOOL(  \
    BOOST_PP_SEQ_SIZE(  \
      BOOST_PP_SEQ_FILTER( PP_DETAIL_ALGORITHM_EXPAND, _,  \
        BOOST_PP_SEQ_FOR_EACH( PP_DETAIL_ALGORITHM_APPLY, mac, BOOST_PP_VARIADIC_TO_SEQ( __VA_ARGS__ ) )  \
        )  \
      )  \
    )

#define PP_VA_NONE_OF( mac, ... )  \
  BOOST_PP_NOT(  \
    BOOST_PP_BOOL(  \
      BOOST_PP_SEQ_SIZE(  \
        BOOST_PP_SEQ_FILTER( PP_DETAIL_ALGORITHM_EXPAND, _,  \
          BOOST_PP_SEQ_FOR_EACH( PP_DETAIL_ALGORITHM_APPLY, mac, BOOST_PP_VARIADIC_TO_SEQ( __VA_ARGS__ ) )  \
          )  \
        )  \
      )  \
    )

#define PP_DETAIL_ALGORITHM_APPLY( r, data, elem )      ( data( elem ) )
#define PP_DETAIL_ALGORITHM_EXPAND( r, data, elem )      elem

#define ARGSa  boo,foo,bar
#define ARGSb  ,,,
#define ARGSc  boo,,bar

// 確認用コード                            // ↓出力
PP_VA_ALL_OF( BOOST_PP_IS_EMPTY, ARGSa );  // 0 
PP_VA_ALL_OF( BOOST_PP_IS_EMPTY, ARGSb );  // 1 
PP_VA_ALL_OF( BOOST_PP_IS_EMPTY, ARGSc );  // 0 
PP_VA_ANY_OF( BOOST_PP_IS_EMPTY, ARGSa );  // 0 
PP_VA_ANY_OF( BOOST_PP_IS_EMPTY, ARGSb );  // 1 
PP_VA_ANY_OF( BOOST_PP_IS_EMPTY, ARGSc );  // 1 
PP_VA_NONE_OF( BOOST_PP_IS_EMPTY, ARGSa ); // 1 
PP_VA_NONE_OF( BOOST_PP_IS_EMPTY, ARGSb ); // 0 
PP_VA_NONE_OF( BOOST_PP_IS_EMPTY, ARGSc ); // 0 


本当は、PP_VA_ANY_OF が欲しくて、


「可変長引数に空引数があると
 Boost.Concept でも使ってわかりやすいビルドエラーにしたい」


という感じで作りました。


マクロのエラーはテンプレのエラーよりも追いかけるのが大変なので…(^_^;)