mirror of
https://github.com/boostorg/fusion.git
synced 2025-07-05 08:36:33 +02:00
320 lines
8.4 KiB
C++
320 lines
8.4 KiB
C++
![]() |
/*=============================================================================
|
||
|
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();
|
||
|
}
|