/*============================================================================= Copyright (c) 2001-2011 Joel de Guzman Copyright (c) 2022 Denis Mikhailov 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) ==============================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct square { template struct result; template struct result { typedef int type; }; template int operator()(T x) const { return x * x; } }; struct add { template struct result; template struct result { typedef int type; }; template int operator()(A a, B b) const { return a + b; } }; struct abstract { virtual void foo() = 0; }; struct functor { typedef boost::fusion::pair pair_0; typedef boost::fusion::pair pair_1; typedef boost::fusion::pair pair_2; typedef boost::mpl::map< boost::mpl::pair< boost::fusion::pair , pair_0> , boost::mpl::pair< pair_1 , pair_1> , boost::mpl::pair< boost::fusion::pair , pair_2> > m; template struct result; template struct result : boost::mpl::at< m, typename boost::remove_reference::type > {}; pair_0 operator() (const boost::fusion::pair& arg) const { return pair_0(arg.second); } pair_1 operator() (const pair_1 & arg) const { return pair_1(arg.second + "_transformed"); } pair_2 operator() (const boost::fusion::pair& arg) const { return pair_2(arg.second); } }; struct simple_identity { template struct result; template struct result { typedef U type; }; template T& operator() (T& arg) const { return arg; } }; struct simple_identity_nonref { template struct result; template struct result : boost::remove_reference {}; template T operator() (T arg) const { return arg; } }; int main() { using namespace boost::fusion; std::cout << tuple_open('['); std::cout << tuple_close(']'); std::cout << tuple_delimiter(", "); /// Testing the transform_view { typedef boost::mpl::range_c sequence_type; sequence_type sequence; square sq; typedef transform_view xform_type; xform_type xform(sequence, sq); std::cout << xform << std::endl; BOOST_TEST((xform == make_vector(25, 36, 49, 64))); typedef boost::fusion::result_of::begin::type first_type; first_type first_it(boost::fusion::begin(xform)); typedef boost::fusion::result_of::next::type next_type; next_type next_it(boost::fusion::next(first_it)); BOOST_TEST((*next_it == 36)); BOOST_TEST((*boost::fusion::prior(next_it) == 25)); BOOST_TEST((boost::fusion::distance(first_it, next_it) == 1)); BOOST_TEST((*boost::fusion::advance_c<3>(boost::fusion::begin(xform)) == 64)); BOOST_TEST((boost::fusion::at_c<2>(xform) == 49)); BOOST_MPL_ASSERT((boost::is_same::type, int>)); } { typedef boost::mpl::range_c sequence1_type; typedef boost::mpl::range_c sequence2_type; sequence1_type sequence1; sequence2_type sequence2; add f; typedef transform_view xform_type; xform_type xform(sequence1, sequence2, f); std::cout << xform << std::endl; BOOST_TEST((xform == make_vector(15, 17, 19, 21))); BOOST_TEST((boost::fusion::at_c<2>(xform) == 19)); BOOST_MPL_ASSERT((boost::is_same::type, int>)); } /// Associative { typedef map< pair , pair , pair > map_type; typedef transform_view transformed_type; BOOST_MPL_ASSERT((traits::is_associative)); BOOST_MPL_ASSERT((traits::is_random_access)); map_type m( make_pair('X') , make_pair("Men") , make_pair(2)); transformed_type t(m, functor()); std::cout << at_key(t) << std::endl; std::cout << at_key(t) << std::endl; std::cout << at_key(t) << std::endl; BOOST_TEST(at_key(t) == 'X'); BOOST_TEST(at_key(t) == "Men_transformed"); BOOST_TEST(at_key(t) == 2); BOOST_STATIC_ASSERT(( boost::is_same::type, char>::value)); BOOST_STATIC_ASSERT(( boost::is_same::type, std::string>::value)); BOOST_STATIC_ASSERT(( boost::is_same::type, long>::value)); std::cout << t << std::endl; BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); BOOST_STATIC_ASSERT((!boost::fusion::result_of::has_key::value)); std::cout << deref_data(begin(t)) << std::endl; std::cout << deref_data(boost::fusion::next(begin(t))) << std::endl; BOOST_TEST(deref_data(begin(t)) == 'X'); BOOST_TEST(deref_data(boost::fusion::next(begin(t))) == "Men_transformed"); BOOST_TEST(deref_data(boost::fusion::next(next(begin(t)))) == 2); BOOST_STATIC_ASSERT((boost::is_same::type>::type, short>::value)); BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type, double>::value)); BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type>::type, abstract>::value)); BOOST_STATIC_ASSERT((boost::is_same::type>::type, char>::value)); BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type, std::string>::value)); BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type>::type, long>::value)); // Test random access interface. pair a = at_c<0>(t); (void) a; pair b = at_c<1>(t); pair c = at_c<2>(t); (void)c; typedef boost::fusion::result_of::begin::type first; typedef boost::fusion::result_of::next::type second; typedef boost::fusion::result_of::next::type third; BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); } { typedef map< pair , pair , pair > map_type; typedef transform_view transformed_type; BOOST_MPL_ASSERT((traits::is_associative)); BOOST_MPL_ASSERT((traits::is_random_access)); map_type m( make_pair('X') , make_pair("Men") , make_pair(2)); transformed_type t(m, simple_identity()); std::cout << at_key(t) << std::endl; std::cout << at_key(t) << std::endl; std::cout << at_key(t) << std::endl; BOOST_TEST(at_key(t) == 'X'); BOOST_TEST(at_key(t) == "Men"); BOOST_TEST(at_key(t) == 2); BOOST_STATIC_ASSERT(( boost::is_same::type, char>::value)); BOOST_STATIC_ASSERT(( boost::is_same::type, std::string>::value)); BOOST_STATIC_ASSERT(( boost::is_same::type, int>::value)); std::cout << t << std::endl; BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); BOOST_STATIC_ASSERT((boost::fusion::result_of::has_key::value)); BOOST_STATIC_ASSERT((!boost::fusion::result_of::has_key::value)); std::cout << deref_data(begin(t)) << std::endl; std::cout << deref_data(boost::fusion::next(begin(t))) << std::endl; BOOST_TEST(deref_data(begin(t)) == 'X'); BOOST_TEST(deref_data(boost::fusion::next(begin(t))) == "Men"); BOOST_TEST(deref_data(boost::fusion::next(next(begin(t)))) == 2); BOOST_STATIC_ASSERT((boost::is_same::type>::type, int>::value)); BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type, double>::value)); BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type>::type, abstract>::value)); BOOST_STATIC_ASSERT((boost::is_same::type>::type, char>::value)); BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type, std::string>::value)); BOOST_STATIC_ASSERT((boost::is_same::type>::type>::type>::type, int>::value)); // Test random access interface. pair a = at_c<0>(t); (void) a; pair b = at_c<1>(t); pair c = at_c<2>(t); (void)c; typedef boost::fusion::result_of::begin::type first; typedef boost::fusion::result_of::next::type second; typedef boost::fusion::result_of::next::type third; // BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); // BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); // BOOST_MPL_ASSERT((boost::is_same::type, boost::fusion::pair >)); } { // compile test only // make sure result_of::deref_data returns a reference typedef map > map_type; typedef transform_view transformed_type; typedef boost::fusion::result_of::begin::type i_type; typedef boost::fusion::result_of::deref_data::type r_type; BOOST_STATIC_ASSERT((boost::is_same::value)); } { // compile test only // make sure result_of::deref_data is const correct typedef map > const map_type; typedef transform_view transformed_type; typedef boost::fusion::result_of::begin::type i_type; typedef boost::fusion::result_of::deref_data::type r_type; BOOST_STATIC_ASSERT((boost::is_same::value)); } { // compile test only // make sure result_of::deref_data will not return a reference to temp object typedef map > const map_type; typedef transform_view transformed_type; typedef boost::fusion::result_of::begin::type i_type; typedef boost::fusion::result_of::deref_data::type r_type; BOOST_STATIC_ASSERT((boost::is_same::value)); } { // compile test only // make sure result_of::deref_data will not const for non-constant references typedef map > const map_type; typedef transform_view transformed_type; typedef boost::fusion::result_of::begin::type i_type; typedef boost::fusion::result_of::deref_data::type r_type; BOOST_STATIC_ASSERT((boost::is_same::value)); } return boost::report_errors(); }