boost::mpl::Assertsの実装の概要


#include <[]boost[]/mpl/bool.hpp>
#include <[]boost[]/mpl/eval_if.hpp>

namespace question {
struct X {
int a;
};

int X::* what_is_this();
int X::** what_is_that();

inline void test_X() {
X x;
// pointer to member a
int X::*p2a = &X::a;
x.*p2a = 10;
p2a = what_is_this();
// pointer to pointer to member a
int X::** pp2a = &p2a;
x.**pp2a = 10;
pp2a = what_is_that();
}
} // question


namespace pst {
namespace mpl = []boost[]::mpl;

struct failed { };

// functors
// "汚い"型名を残すためにtypedefを使わずexecの戻り値の型を使う
template< typename Pred >
struct ftor_ret_true_ {
mpl::true_ exec();
typedef ftor_ret_true_ type;
};

template< typename Pred >
struct ftor_ret_failed {
failed************ Pred::************ exec();
typedef ftor_ret_failed type;
};

// dispatcher
template< typename Pred >
struct ftor_ret_true_or_failed
: mpl::eval_if< Pred, ftor_ret_true_<Pred>, ftor_ret_failed<Pred> >::type { };

// テンプレート引数にはftor_ret_true_or_failed<(pred)>のように
// ()を付けられない、しかしマクロ引数には()を付けないといけない。そこで、
template< typename Pred >
ftor_ret_true_or_failed<Pred>
make_ftor_ret_true_or_failed( void (*) (Pred) );

int assertion_failed(mpl::true_);
} // pst

#define PST_MPL_ASSERT(pred) \
enum { \
pst_mpl_assertion_in_line_12345 = sizeof( \
pst::assertion_failed( \
pst::make_ftor_ret_true_or_failed( (void (*) pred)0 ).exec() \
) \
) \
}\

#include <[]boost[]/type_traits.hpp>

PST_MPL_ASSERT( ( []boost[]::is_same<int, int> ) );
PST_MPL_ASSERT( ( []boost[]::is_same<char, int> ) );