
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*); }