| /*============================================================================= |
| Copyright (c) 2001-2006 Joel de Guzman |
| 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/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 |
| mpl::if_< |
| boost::is_const<Sq> |
| , typename Sq::t0_type const& |
| , typename Sq::t0_type& |
| >::type |
| 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 |
| mpl::if_< |
| boost::is_const<Sq> |
| , typename Sq::t1_type const& |
| , typename Sq::t1_type& |
| >::type |
| 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 |
| mpl::if_< |
| boost::is_const<Sq> |
| , typename Sq::t2_type const& |
| , typename Sq::t2_type& |
| >::type |
| 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; |
| }; |
| } |
| |
| 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"); |
| return boost::report_errors(); |
| } |