Boost logo

Boost :

From: Tobias Schwinger (tschwinger_at_[hidden])
Date: 2004-09-19 06:17:47


Tobias Schwinger wrote:
> I attached some experimental source code

Hrm... Did I ? ;+)

Here's the missing attachment


#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/config.hpp>
#include <boost/type_traits/add_reference.hpp>

using namespace boost;

  /////////////////////////////////////////////////////////////////////////////
// Type categories

struct integral
{
  integral(char);
  integral(short);
  integral(int);
  integral(long);
};

struct real
{
  real(float);
  real(double);
};

struct pointer
{
  template <typename T>
  pointer(T*);
};

  /////////////////////////////////////////////////////////////////////////////
// States of the filter

enum { pass = 1, filter_true = 2, filter_false = 3 };

typedef char (& pass_type ) [pass];
typedef char (& filter_true_type ) [filter_true];
typedef char (& filter_false_type ) [filter_false];

  /////////////////////////////////////////////////////////////////////////////
// Filtering rule set

pass_type BOOST_TT_DECL filter(...);

// type combinations matching builtin types
filter_true_type filter(integral,integral);
filter_true_type filter(integral,pointer);
filter_true_type filter(integral,real);
filter_true_type filter(real,integral);
filter_true_type filter(real,real);
filter_true_type filter(pointer,integral);

// impossible type combinations
filter_false_type filter(real,pointer);
filter_false_type filter(pointer,real);
filter_false_type filter(pointer,pointer);

  /////////////////////////////////////////////////////////////////////////////
// The filter implementation

template <typename T1, typename T2, typename Operation>
struct op_test_input_filter
{
private:

  static typename add_reference<T1>::type arg1;
  static typename add_reference<T2>::type arg2;

  BOOST_STATIC_CONSTANT(int, state = ( sizeof(filter(arg1, arg2)) ));

public:

  typedef typename mpl::eval_if_c< (state == pass)
                                 , typename Operation::apply<T1,T2>
                                 , mpl::bool_<state == filter_true>
>::type type;
  BOOST_STATIC_CONSTANT(bool, value = ( type::value ));
};

// Specializations for void arguments could come here.

  /////////////////////////////////////////////////////////////////////////////
// Test for the filter implementation above

// These are used in place of a "real" operator checker to test the filtering
// behaviour.

struct always // ::type is always mpl::bool_<true> regardless of the argumetns
{
  template <typename T1, typename T2>
  struct apply
  {
    typedef mpl::bool_<true> type;
  };
};

struct never // ::type is always mpl::bool_<false> regardless of the arguments
{
  template <typename T1, typename T2>
  struct apply
  {
    typedef mpl::bool_<false> type;
  };
};

struct illegal // is not instantiatable
{
  template <typename T1, typename T2>
  struct apply
  {
    BOOST_STATIC_ASSERT(false);
  };
};

// If the combination of type arguments is matched by the filter, the result
// must not depend on the specified operation.

#define ASSERT_FILTER(type1,type2) \
  BOOST_STATIC_ASSERT(( op_test_input_filter<type1,type2,always>::value \
                     == op_test_input_filter<type1,type2,never>::value ))

// The combination of type arguments is matched by the filter and the result
// is "true". The operation passed results in an error when instantiated.

#define ASSERT_FILTER_TRUE_RESULT(type1,type2) \
  ASSERT_FILTER(type1,type2); \
  BOOST_STATIC_ASSERT(( op_test_input_filter<type1,type2,illegal>::value ))

// The combination of type arguments is matched by the filter and the result
// is "false". The operation passed results in an error when instantiated.

#define ASSERT_FILTER_FALSE_RESULT(type1,type2) \
  ASSERT_FILTER(type1,type2); \
  BOOST_STATIC_ASSERT(!( op_test_input_filter<type1,type2,illegal>::value ))

// If the combination of type arguments is unmatched by the filter, the
// result must only depend on the specified operation.

#define ASSERT_PASS(type1,type2) \
  BOOST_STATIC_ASSERT(( op_test_input_filter<type1,type2,always>::value \
                     != op_test_input_filter<type1,type2,never>::value ))

struct foo { };
struct bar { };

int main()
{
  ASSERT_PASS(foo,bar);
  ASSERT_PASS(foo,foo);

  ASSERT_FILTER_TRUE_RESULT(int,int);
  ASSERT_FILTER_TRUE_RESULT(char,int);
  ASSERT_FILTER_TRUE_RESULT(char,char);
  ASSERT_FILTER_TRUE_RESULT(int,int*);

  ASSERT_FILTER_FALSE_RESULT(int*,float);
  ASSERT_FILTER_FALSE_RESULT(int*,int*);
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk