diff --git a/test/enable_if_lazy.cpp b/test/enable_if_lazy.cpp index b9324e8..4ffd3ec 100644 --- a/test/enable_if_lazy.cpp +++ b/test/enable_if_lazy.cpp @@ -11,64 +11,68 @@ #include #include -#include +#include using boost::enable_if_c; using boost::lazy_enable_if_c; -using boost::is_arithmetic; -// This class provides a reduced example of a traits class for computing -// the result of multiplying two types. The exists constant is true when a -// multiplication operator exists between two types, and the type member is -// defined to the return type of this operator. The return type member is -// not defined when a multiplication operator does not exist. +// This class provides a reduced example of a traits class for +// computing the result of multiplying two types. The member typedef +// 'type' in this traits class defines the return type of this +// operator. The return type member is invalid unless both arguments +// for mult_traits are values that mult_traits expects (ints in this +// case). This kind of situation may arise if a traits class only +// makes sense for some set of types, not all C++ types. + +template struct is_int { + BOOST_STATIC_CONSTANT(bool, value = (boost::is_same::value)); +}; template struct mult_traits { - BOOST_STATIC_CONSTANT(bool, exists = false); + typedef typename T::does_not_exist type; }; template <> struct mult_traits { - BOOST_STATIC_CONSTANT(bool, exists = true); typedef int type; }; -template <> -struct mult_traits { - BOOST_STATIC_CONSTANT(bool, exists = true); - typedef double type; -}; -// Next, a forwarding function mult() is defined. It is enabled only when -// mult_traits::exists is true. The first version, using normal -// enable_if_c, works with only some compilers (it does not work in g++): +// Next, a forwarding function mult() is defined. It is enabled only +// when both arguments are of type int. The first version, using +// non-lazy enable_if_c does not work. #if 0 template typename enable_if_c< - mult_traits::exists, - typename mult_traits::type>::type + is_int::value && is_int::value, + typename mult_traits::type +>::type mult(const T& x, const U& y) {return x * y;} #endif -// An improved version that works with more compilers uses lazy_enable_if_c. +// A correct version uses lazy_enable_if_c. // This template removes compiler errors from invalid code used as an // argument to enable_if_c. +#if 1 template typename lazy_enable_if_c< - mult_traits::exists, - mult_traits >::type + is_int::value && is_int::value, + mult_traits +>::type mult(const T& x, const U& y) {return x * y;} +#endif double mult(int i, double d) { return (double)i * d; } int test_main(int, char*[]) { - + + BOOST_CHECK(mult(1, 2) == 2); - BOOST_CHECK(mult(1.0, 3.0) == 3.0); + BOOST_CHECK(mult(1, 3.0) == 3.0); return 0; diff --git a/test/enable_if_lazy_test.cpp b/test/enable_if_lazy_test.cpp index 1c4d25d..8f90016 100644 --- a/test/enable_if_lazy_test.cpp +++ b/test/enable_if_lazy_test.cpp @@ -8,11 +8,13 @@ // Andrew Lumsdaine (lums at osl.iu.edu) // +// Testing all variations of lazy_enable_if. + #include #include #include -#include +#include using boost::lazy_enable_if; using boost::lazy_disable_if; @@ -20,22 +22,26 @@ using boost::lazy_disable_if; using boost::lazy_enable_if_c; using boost::lazy_disable_if_c; -using boost::is_arithmetic; + +template +struct is_int_or_double { + BOOST_STATIC_CONSTANT(bool, + value = (boost::is_same::value || + boost::is_same::value)); +}; template struct some_traits { - BOOST_STATIC_CONSTANT(bool, value = false); + typedef typename T::does_not_exist type; }; template <> struct some_traits { - BOOST_STATIC_CONSTANT(bool, value = true); typedef bool type; }; template <> struct some_traits { - BOOST_STATIC_CONSTANT(bool, value = true); typedef bool type; }; @@ -53,21 +59,21 @@ struct make_bool {}; namespace A { template - typename lazy_enable_if, some_traits >::type + typename lazy_enable_if, some_traits >::type foo(T t) { return true; } template - typename lazy_enable_if_c::value, some_traits >::type + typename lazy_enable_if_c::value, some_traits >::type foo2(T t) { return true; } } namespace B { template - typename lazy_disable_if, make_bool >::type + typename lazy_disable_if, make_bool >::type foo(T t) { return false; } template - typename lazy_disable_if_c::value, make_bool >::type + typename lazy_disable_if_c::value, make_bool >::type foo2(T t) { return false; } }