diff options
Diffstat (limited to 'src/boost/libs/fusion/example/extension/triple.cpp')
-rw-r--r-- | src/boost/libs/fusion/example/extension/triple.cpp | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/src/boost/libs/fusion/example/extension/triple.cpp b/src/boost/libs/fusion/example/extension/triple.cpp new file mode 100644 index 00000000..ac8f18e0 --- /dev/null +++ b/src/boost/libs/fusion/example/extension/triple.cpp @@ -0,0 +1,377 @@ +/*============================================================================= + 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(); +} |