123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- /*=============================================================================
- 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<T0, T1, T2>
- We use fusion::sequence_facade and fusion::iterator_facade
- to make our triple a fully conforming Boost.Fusion random
- traversal sequence.
- ==============================================================================*/
- #include <boost/detail/lightweight_test.hpp>
- #include <boost/fusion/sequence/sequence_facade.hpp>
- #include <boost/fusion/iterator/iterator_facade.hpp>
- #include <boost/fusion/sequence/intrinsic.hpp>
- #include <boost/fusion/iterator.hpp>
- #include <boost/fusion/support/category_of.hpp>
- #include <boost/fusion/algorithm/iteration/fold.hpp>
- #include <boost/mpl/int.hpp>
- #include <boost/mpl/identity.hpp>
- #include <boost/mpl/minus.hpp>
- #include <boost/mpl/assert.hpp>
- #include <boost/type_traits/is_const.hpp>
- #include <boost/type_traits/is_same.hpp>
- #include <string>
- namespace mpl = boost::mpl;
- namespace fusion = boost::fusion;
- namespace demo
- {
- template<typename Seq, int N>
- struct triple_iterator
- : fusion::iterator_facade<triple_iterator<Seq, N>,
- fusion::random_access_traversal_tag>
- {
- typedef mpl::int_<N> index;
- typedef Seq sequence_type;
- triple_iterator(Seq& seq)
- : seq_(seq) {}
- Seq& seq_;
- template<typename T>
- struct value_of;
- template<typename Sq>
- struct value_of<triple_iterator<Sq, 0> >
- : mpl::identity<typename Sq::t0_type>
- {};
- template<typename Sq>
- struct value_of<triple_iterator<Sq, 1> >
- : mpl::identity<typename Sq::t1_type>
- {};
- template<typename Sq>
- struct value_of<triple_iterator<Sq, 2> >
- : mpl::identity<typename Sq::t2_type>
- {};
- template<typename T>
- struct deref;
- template <typename Sq>
- struct deref<triple_iterator<Sq, 0> >
- {
- typedef typename Sq::t0_type& type;
- static type
- call(triple_iterator<Sq, 0> const& iter)
- {
- return iter.seq_.t0;
- }
- };
- template <typename Sq>
- struct deref<triple_iterator<Sq, 0> const>
- {
- typedef typename Sq::t0_type const& type;
- static type
- call(triple_iterator<Sq, 0> const& iter)
- {
- return iter.seq_.t0;
- }
- };
- template <typename Sq>
- struct deref<triple_iterator<Sq, 1> >
- {
- typedef typename Sq::t1_type& type;
- static type
- call(triple_iterator<Sq, 1> const& iter)
- {
- return iter.seq_.t1;
- }
- };
- template <typename Sq>
- struct deref<triple_iterator<Sq, 1> const>
- {
- typedef typename Sq::t1_type const& type;
- static type
- call(triple_iterator<Sq, 1> const& iter)
- {
- return iter.seq_.t1;
- }
- };
- template <typename Sq>
- struct deref<triple_iterator<Sq, 2> >
- {
- typedef typename Sq::t2_type& type;
- static type
- call(triple_iterator<Sq, 2> const& iter)
- {
- return iter.seq_.t2;
- }
- };
- template <typename Sq>
- struct deref<triple_iterator<Sq, 2> const>
- {
- typedef typename Sq::t2_type const& type;
- static type
- call(triple_iterator<Sq, 2> const& iter)
- {
- return iter.seq_.t2;
- }
- };
- template<typename It>
- 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<typename It>
- 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<typename It1, typename It2>
- 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<typename It, typename M>
- 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<typename T0, typename T1, typename T2>
- struct triple
- : fusion::sequence_facade<triple<T0, T1, T2>,
- fusion::random_access_traversal_tag>
- {
- triple(T0 const& t0, T1 const& t1, T2 const& t2)
- : t0(t0), t1(t1), t2(t2)
- {}
- template<typename Sq>
- struct begin
- {
- typedef demo::triple_iterator<Sq, 0> type;
- static type call(Sq& sq)
- {
- return type(sq);
- }
- };
- template<typename Sq>
- struct end
- {
- typedef demo::triple_iterator<Sq, 3> type;
- static type call(Sq& sq)
- {
- return type(sq);
- }
- };
- template<typename Sq>
- struct size
- : mpl::int_<3>
- {};
- template<typename Sq, typename N>
- struct value_at
- : value_at<Sq, mpl::int_<N::value> >
- {};
- template<typename Sq>
- struct value_at<Sq, mpl::int_<0> >
- {
- typedef typename Sq::t0_type type;
- };
- template<typename Sq>
- struct value_at<Sq, mpl::int_<1> >
- {
- typedef typename Sq::t1_type type;
- };
- template<typename Sq>
- struct value_at<Sq, mpl::int_<2> >
- {
- typedef typename Sq::t2_type type;
- };
- template<typename Sq, typename N>
- struct at
- : at<Sq, mpl::int_<N::value> >
- {};
- template<typename Sq>
- struct at<Sq, mpl::int_<0> >
- {
- typedef typename
- mpl::if_<
- boost::is_const<Sq>
- , typename Sq::t0_type const&
- , typename Sq::t0_type&
- >::type
- type;
- static type call(Sq& sq)
- {
- return sq.t0;
- }
- };
- template<typename Sq>
- struct at<Sq, mpl::int_<1> >
- {
- typedef typename
- mpl::if_<
- boost::is_const<Sq>
- , typename Sq::t1_type const&
- , typename Sq::t1_type&
- >::type
- type;
- static type call(Sq& sq)
- {
- return sq.t1;
- }
- };
- template<typename Sq>
- struct at<Sq, mpl::int_<2> >
- {
- typedef typename
- mpl::if_<
- boost::is_const<Sq>
- , 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 <typename T>
- struct result
- {
- typedef bool type;
- };
- template <typename T>
- bool operator()(bool b, T&)
- {
- return b;
- }
- };
- struct nonmodifying_fold_functor
- {
- template <typename T>
- struct result
- {
- typedef bool type;
- };
- template <typename T>
- bool operator()(bool b, const T&)
- {
- return b;
- }
- };
- int main()
- {
- typedef demo::triple<int, char, std::string> 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<my_triple, 0>::type>));
- BOOST_MPL_ASSERT((boost::is_same<
- char, fusion::result_of::value_at_c<my_triple, 1>::type>));
- BOOST_MPL_ASSERT((boost::is_same<
- std::string, fusion::result_of::value_at_c<my_triple, 2>::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();
- }
|