/*============================================================================= Copyright (c) 2001-2011 Joel de Guzman Copyright (c) 2011 Nathan Ridge Copyright (c) 2006 Dan Marsden 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) ==============================================================================*/ /*============================================================================= An implementation of a std::pair like triple We use fusion::sequence_facade and fusion::iterator_facade to make our triple a fully conforming Boost.Fusion random traversal sequence. ==============================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace mpl = boost::mpl; namespace fusion = boost::fusion; namespace demo { template struct triple_iterator : fusion::iterator_facade, fusion::random_access_traversal_tag> { typedef mpl::int_ index; typedef Seq sequence_type; triple_iterator(Seq& seq) : seq_(seq) {} Seq& seq_; template struct value_of; template struct value_of > : mpl::identity {}; template struct value_of > : mpl::identity {}; template struct value_of > : mpl::identity {}; template struct deref; template struct deref > { typedef typename Sq::t0_type& type; static type call(triple_iterator const& iter) { return iter.seq_.t0; } }; template struct deref const> { typedef typename Sq::t0_type const& type; static type call(triple_iterator const& iter) { return iter.seq_.t0; } }; template struct deref > { typedef typename Sq::t1_type& type; static type call(triple_iterator const& iter) { return iter.seq_.t1; } }; template struct deref const> { typedef typename Sq::t1_type const& type; static type call(triple_iterator const& iter) { return iter.seq_.t1; } }; template struct deref > { typedef typename Sq::t2_type& type; static type call(triple_iterator const& iter) { return iter.seq_.t2; } }; template struct deref const> { typedef typename Sq::t2_type const& type; static type call(triple_iterator const& iter) { return iter.seq_.t2; } }; template struct next { typedef triple_iterator< typename It::sequence_type, It::index::value + 1> type; static type call(It const& it) { return type(it.seq_); } }; template struct prior { typedef triple_iterator< typename It::sequence_type, It::index::value - 1> type; static type call(It const& it) { return type(it.seq_); } }; template struct distance { typedef typename mpl::minus< typename It2::index, typename It1::index>::type type; static type call(It1 const& it1, It2 const& it2) { return type(); } }; template struct advance { typedef triple_iterator< typename It::sequence_type, It::index::value + M::value> type; static type call(It const& it) { return type(it.seq_); } }; }; template struct triple : fusion::sequence_facade, fusion::random_access_traversal_tag> { triple(T0 const& t0, T1 const& t1, T2 const& t2) : t0(t0), t1(t1), t2(t2) {} template struct begin { typedef demo::triple_iterator type; static type call(Sq& sq) { return type(sq); } }; template struct end { typedef demo::triple_iterator type; static type call(Sq& sq) { return type(sq); } }; template struct size : mpl::int_<3> {}; template struct value_at : value_at > {}; template struct value_at > { typedef typename Sq::t0_type type; }; template struct value_at > { typedef typename Sq::t1_type type; }; template struct value_at > { typedef typename Sq::t2_type type; }; template struct at : at > {}; template struct at > { typedef typename mpl::if_< boost::is_const , typename Sq::t0_type const& , typename Sq::t0_type& >::type type; static type call(Sq& sq) { return sq.t0; } }; template struct at > { typedef typename mpl::if_< boost::is_const , typename Sq::t1_type const& , typename Sq::t1_type& >::type type; static type call(Sq& sq) { return sq.t1; } }; template struct at > { typedef typename mpl::if_< boost::is_const , typename Sq::t2_type const& , typename Sq::t2_type& >::type type; static type call(Sq& sq) { return sq.t2; } }; typedef T0 t0_type; typedef T1 t1_type; typedef T2 t2_type; T0 t0; T1 t1; T2 t2; }; } struct modifying_fold_functor { template struct result { typedef bool type; }; template bool operator()(bool b, T&) { return b; } }; struct nonmodifying_fold_functor { template struct result { typedef bool type; }; template bool operator()(bool b, const T&) { return b; } }; int main() { typedef demo::triple my_triple; my_triple t(101, 'a', "hello"); BOOST_TEST(*fusion::begin(t) == 101); BOOST_TEST(*fusion::next(fusion::begin(t)) == 'a'); BOOST_TEST(*fusion::prior(fusion::end(t)) == "hello"); BOOST_TEST(fusion::distance(fusion::begin(t), fusion::end(t)) == 3); BOOST_TEST(fusion::size(t) == 3); BOOST_MPL_ASSERT((boost::is_same< int, fusion::result_of::value_at_c::type>)); BOOST_MPL_ASSERT((boost::is_same< char, fusion::result_of::value_at_c::type>)); BOOST_MPL_ASSERT((boost::is_same< std::string, fusion::result_of::value_at_c::type>)); BOOST_TEST(fusion::at_c<0>(t) == 101); BOOST_TEST(fusion::at_c<1>(t) == 'a'); BOOST_TEST(fusion::at_c<2>(t) == "hello"); BOOST_TEST(fusion::fold(t, true, modifying_fold_functor()) == true); BOOST_TEST(fusion::fold(t, true, nonmodifying_fold_functor()) == true); return boost::report_errors(); }