// Boost.TypeErasure library // // Copyright 2015 Steven Watanabe // // Distributed under the Boost Software License Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // $Id$ #include #include #include #include #include #include #include #define BOOST_TEST_MAIN #include using namespace boost::type_erasure; template struct common : ::boost::mpl::vector< copy_constructible, typeid_ > {}; struct fixture { fixture() { register_binding, int>(); register_binding, int>(); register_binding >(make_binding, boost::mpl::pair<_a, int> > >()); } }; BOOST_GLOBAL_FIXTURE(fixture); BOOST_AUTO_TEST_CASE(test_identical) { any > x(1); any > y = dynamic_any_cast > >(x); BOOST_CHECK_EQUAL(any_cast(y), 1); } BOOST_AUTO_TEST_CASE(test_downcast) { any > x(1); typedef any< ::boost::mpl::vector, incrementable<> > > incrementable_any; incrementable_any y = dynamic_any_cast(x); ++y; BOOST_CHECK_EQUAL(any_cast(y), 2); } BOOST_AUTO_TEST_CASE(test_cross_cast) { any< ::boost::mpl::vector, decrementable<> > > x(1); typedef any< ::boost::mpl::vector, incrementable<> > > incrementable_any; incrementable_any y = dynamic_any_cast(x); ++y; BOOST_CHECK_EQUAL(any_cast(y), 2); } BOOST_AUTO_TEST_CASE(test_cast_placeholder) { any > x(1); typedef any< ::boost::mpl::vector, incrementable<_a> >, _a> incrementable_any; incrementable_any y = dynamic_any_cast(x); ++y; BOOST_CHECK_EQUAL(any_cast(y), 2); } BOOST_AUTO_TEST_CASE(test_throw) { any > x("42"); typedef any< ::boost::mpl::vector, incrementable<_a> >, _a> incrementable_any; BOOST_CHECK_THROW(dynamic_any_cast(x), bad_any_cast); } // make sure that a function registered with _self can // be found with _a. BOOST_AUTO_TEST_CASE(test_other_placeholder) { any, _a> x(1); typedef any< ::boost::mpl::vector, incrementable<_a> >, _a> incrementable_any; incrementable_any y = dynamic_any_cast(x); ++y; BOOST_CHECK_EQUAL(any_cast(y), 2); } // Casting to a value only requires the target to provide // a copy constructor. BOOST_AUTO_TEST_CASE(test_add_copy) { any< ::boost::mpl::vector, typeid_<> > > x(1); any > y = dynamic_any_cast > >(x); BOOST_CHECK_EQUAL(any_cast(y), 1); } template struct choose_second { typedef U type; }; BOOST_AUTO_TEST_CASE(test_deduced) { typedef deduced > _p2; any< ::boost::mpl::vector, common<_p2> > > x(1); typedef ::boost::mpl::vector, common<_p2>, incrementable<_p2>, addable<_self, _self, _p2> > dest_concept; any y = dynamic_any_cast >(x); any z = y + y; ++z; BOOST_CHECK_EQUAL(any_cast(z), 3); } BOOST_AUTO_TEST_CASE(test_multiple_placeholders) { typedef ::boost::mpl::map< ::boost::mpl::pair<_a, int>, boost::mpl::pair<_b, int> > init_map; any< ::boost::mpl::vector, common<_b> >, _a> x(1, make_binding()); typedef ::boost::mpl::vector, common<_b>, incrementable<_b>, addable<_a, _a, _b> > dest_concept; typedef ::boost::mpl::map< ::boost::mpl::pair<_a, _a>, ::boost::mpl::pair<_b, _b> > placeholder_map; any y = dynamic_any_cast >(x, make_binding()); any z = y + y; ++z; BOOST_CHECK_EQUAL(any_cast(z), 3); } BOOST_AUTO_TEST_CASE(test_multiple_placeholders_switch) { typedef ::boost::mpl::map< ::boost::mpl::pair<_a, int>, boost::mpl::pair<_b, int> > init_map; any< ::boost::mpl::vector, common<_b> >, _a> x(1, make_binding()); typedef ::boost::mpl::vector, common<_d>, incrementable<_d>, addable<_c, _c, _d> > dest_concept; typedef ::boost::mpl::map< ::boost::mpl::pair<_c, _a>, ::boost::mpl::pair<_d, _b> > placeholder_map; any y = dynamic_any_cast >(x, make_binding()); any z = y + y; ++z; BOOST_CHECK_EQUAL(any_cast(z), 3); } template T as_rvalue(const T& arg) { return arg; } template const T& as_const(const T& arg) { return arg; } BOOST_AUTO_TEST_CASE(test_val) { any > x(1); // value any > y1 = dynamic_any_cast > >(x); BOOST_CHECK_EQUAL(any_cast(x), any_cast(y1)); any > y2 = dynamic_any_cast > >(as_rvalue(x)); BOOST_CHECK_EQUAL(any_cast(x), any_cast(y2)); any > y3 = dynamic_any_cast > >(as_const(x)); BOOST_CHECK_EQUAL(any_cast(x), any_cast(y3)); // lvalue reference any, _self&> r(x); any > z1 = dynamic_any_cast > >(r); BOOST_CHECK_EQUAL(any_cast(x), any_cast(z1)); any > z2 = dynamic_any_cast > >(as_rvalue(r)); BOOST_CHECK_EQUAL(any_cast(x), any_cast(z2)); any > z3 = dynamic_any_cast > >(as_const(r)); BOOST_CHECK_EQUAL(any_cast(x), any_cast(z3)); // const reference any, const _self&> cr(x); any > w1 = dynamic_any_cast > >(cr); BOOST_CHECK_EQUAL(any_cast(x), any_cast(w1)); any > w2 = dynamic_any_cast > >(as_rvalue(cr)); BOOST_CHECK_EQUAL(any_cast(x), any_cast(w2)); any > w3 = dynamic_any_cast > >(as_const(cr)); BOOST_CHECK_EQUAL(any_cast(x), any_cast(w3)); #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES // rvalue reference any, _self&&> rr(std::move(x)); any > v1 = dynamic_any_cast > >(rr); BOOST_CHECK_EQUAL(any_cast(x), any_cast(v1)); any > v2 = dynamic_any_cast > >(as_rvalue(rr)); BOOST_CHECK_EQUAL(any_cast(x), any_cast(v2)); any > v3 = dynamic_any_cast > >(as_const(rr)); BOOST_CHECK_EQUAL(any_cast(x), any_cast(v3)); #endif } BOOST_AUTO_TEST_CASE(test_ref) { // A non-const reference can only bind to a few cases any > x(1); any, _self&> y = dynamic_any_cast, _self&> >(x); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&y)); any, _self&> z = dynamic_any_cast, _self&> >(y); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&z)); any, _self&> w = dynamic_any_cast, _self&> >(as_rvalue(y)); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&w)); any, _self&> v = dynamic_any_cast, _self&> >(as_const(y)); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&v)); } BOOST_AUTO_TEST_CASE(test_cref) { any > x(1); typedef any, const _self&> dest_type; // value dest_type y1 = dynamic_any_cast(x); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&y1)); // as_rvalue creates a temporary BOOST_CHECK_EQUAL(any_cast(x), any_cast(dynamic_any_cast(as_rvalue(x)))); dest_type y3 = dynamic_any_cast(as_const(x)); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&y3)); // lvalue reference any, _self&> r(x); dest_type z1 = dynamic_any_cast(r); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&z1)); dest_type z2 = dynamic_any_cast(as_rvalue(r)); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&z2)); dest_type z3 = dynamic_any_cast(as_const(r)); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&z3)); // const reference any, const _self&> cr(x); dest_type w1 = dynamic_any_cast(cr); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&w1)); dest_type w2 = dynamic_any_cast(as_rvalue(cr)); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&w2)); dest_type w3 = dynamic_any_cast(as_const(cr)); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&w3)); #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES // rvalue reference any, _self&&> rr(std::move(x)); dest_type v1 = dynamic_any_cast(rr); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&v1)); dest_type v2 = dynamic_any_cast(as_rvalue(rr)); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&v2)); dest_type v3 = dynamic_any_cast(as_const(rr)); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&v3)); #endif } #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES BOOST_AUTO_TEST_CASE(test_rref) { any > x(1); typedef any, _self&&> dest_type; // value dest_type y2 = dynamic_any_cast(std::move(x)); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&y2)); // rvalue reference any, _self&&> rr(std::move(x)); dest_type v2 = dynamic_any_cast(std::move(rr)); BOOST_CHECK_EQUAL(any_cast(&x), any_cast(&v2)); } #endif