310 lines
8.1 KiB
C++
310 lines
8.1 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// cons.hpp
|
|
//
|
|
// Copyright 2008 Eric Niebler. 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)
|
|
|
|
#ifndef BOOST_XPRESSIVE_DETAIL_UTILITY_CONS_HPP_EAN_11_19_2005
|
|
#define BOOST_XPRESSIVE_DETAIL_UTILITY_CONS_HPP_EAN_11_19_2005
|
|
|
|
#include <boost/version.hpp>
|
|
|
|
#if BOOST_VERSION >= 103300
|
|
|
|
// In Boost 1.33+, we have a cons list in Fusion, so just include it.
|
|
|
|
# if BOOST_VERSION >= 103500
|
|
# include <boost/fusion/include/cons.hpp> // Boost 1.35+ has Fusion2
|
|
# else
|
|
# include <boost/spirit/fusion/sequence/cons.hpp> // Fusion1
|
|
# endif
|
|
|
|
#else
|
|
|
|
// For earlier versions of Boost, put the definition of cons here
|
|
# include <boost/call_traits.hpp>
|
|
# include <boost/mpl/if.hpp>
|
|
# include <boost/mpl/eval_if.hpp>
|
|
# include <boost/mpl/identity.hpp>
|
|
# include <boost/type_traits/is_const.hpp>
|
|
# include <boost/type_traits/add_const.hpp>
|
|
# include <boost/type_traits/add_reference.hpp>
|
|
# include <boost/spirit/fusion/detail/config.hpp>
|
|
# include <boost/spirit/fusion/detail/access.hpp>
|
|
# include <boost/spirit/fusion/iterator/next.hpp>
|
|
# include <boost/spirit/fusion/iterator/equal_to.hpp>
|
|
# include <boost/spirit/fusion/iterator/as_fusion_iterator.hpp>
|
|
# include <boost/spirit/fusion/iterator/detail/iterator_base.hpp>
|
|
# include <boost/spirit/fusion/sequence/begin.hpp>
|
|
# include <boost/spirit/fusion/sequence/end.hpp>
|
|
# include <boost/spirit/fusion/sequence/as_fusion_sequence.hpp>
|
|
# include <boost/spirit/fusion/sequence/detail/sequence_base.hpp>
|
|
|
|
namespace boost { namespace fusion
|
|
{
|
|
struct nil;
|
|
|
|
struct cons_tag;
|
|
|
|
template <typename Car, typename Cdr>
|
|
struct cons;
|
|
|
|
struct cons_iterator_tag;
|
|
|
|
template <typename Cons>
|
|
struct cons_iterator;
|
|
|
|
namespace cons_detail
|
|
{
|
|
template <typename Iterator>
|
|
struct deref_traits_impl
|
|
{
|
|
typedef typename Iterator::cons_type cons_type;
|
|
typedef typename cons_type::car_type value_type;
|
|
|
|
typedef typename mpl::eval_if<
|
|
is_const<cons_type>
|
|
, add_reference<typename add_const<value_type>::type>
|
|
, add_reference<value_type> >::type
|
|
type;
|
|
|
|
static type
|
|
call(Iterator const& i)
|
|
{
|
|
return detail::ref(i.cons.car);
|
|
}
|
|
};
|
|
|
|
template <typename Iterator>
|
|
struct next_traits_impl
|
|
{
|
|
typedef typename Iterator::cons_type cons_type;
|
|
typedef typename cons_type::cdr_type cdr_type;
|
|
|
|
typedef cons_iterator<
|
|
typename mpl::eval_if<
|
|
is_const<cons_type>
|
|
, add_const<cdr_type>
|
|
, mpl::identity<cdr_type>
|
|
>::type>
|
|
type;
|
|
|
|
static type
|
|
call(Iterator const& i)
|
|
{
|
|
return type(detail::ref(i.cons.cdr));
|
|
}
|
|
};
|
|
|
|
template <typename Iterator>
|
|
struct value_traits_impl
|
|
{
|
|
typedef typename Iterator::cons_type cons_type;
|
|
typedef typename cons_type::car_type type;
|
|
};
|
|
|
|
template <typename Cons>
|
|
struct begin_traits_impl
|
|
{
|
|
typedef cons_iterator<Cons> type;
|
|
|
|
static type
|
|
call(Cons& t)
|
|
{
|
|
return type(t);
|
|
}
|
|
};
|
|
|
|
template <typename Cons>
|
|
struct end_traits_impl
|
|
{
|
|
typedef cons_iterator<
|
|
typename mpl::if_<is_const<Cons>, nil const, nil>::type>
|
|
type;
|
|
|
|
static type
|
|
call(Cons& t)
|
|
{
|
|
FUSION_RETURN_DEFAULT_CONSTRUCTED;
|
|
}
|
|
};
|
|
} // namespace cons_detail
|
|
|
|
namespace meta
|
|
{
|
|
template <typename Tag>
|
|
struct deref_impl;
|
|
|
|
template <>
|
|
struct deref_impl<cons_iterator_tag>
|
|
{
|
|
template <typename Iterator>
|
|
struct apply : cons_detail::deref_traits_impl<Iterator> {};
|
|
};
|
|
|
|
template <typename Tag>
|
|
struct next_impl;
|
|
|
|
template <>
|
|
struct next_impl<cons_iterator_tag>
|
|
{
|
|
template <typename Iterator>
|
|
struct apply : cons_detail::next_traits_impl<Iterator> {};
|
|
};
|
|
|
|
template <typename Tag>
|
|
struct value_impl;
|
|
|
|
template <>
|
|
struct value_impl<cons_iterator_tag>
|
|
{
|
|
template <typename Iterator>
|
|
struct apply : cons_detail::value_traits_impl<Iterator> {};
|
|
};
|
|
|
|
template <typename Tag>
|
|
struct begin_impl;
|
|
|
|
template <>
|
|
struct begin_impl<cons_tag>
|
|
{
|
|
template <typename Sequence>
|
|
struct apply : cons_detail::begin_traits_impl<Sequence>
|
|
{};
|
|
};
|
|
|
|
template <typename Tag>
|
|
struct end_impl;
|
|
|
|
template <>
|
|
struct end_impl<cons_tag>
|
|
{
|
|
template <typename Sequence>
|
|
struct apply : cons_detail::end_traits_impl<Sequence>
|
|
{};
|
|
};
|
|
} // namespace meta
|
|
|
|
template <typename Cons = nil>
|
|
struct cons_iterator : iterator_base<cons_iterator<Cons> >
|
|
{
|
|
typedef cons_iterator_tag tag;
|
|
typedef Cons cons_type;
|
|
|
|
explicit cons_iterator(cons_type& cons_)
|
|
: cons(cons_) {}
|
|
|
|
cons_type& cons;
|
|
};
|
|
|
|
template <>
|
|
struct cons_iterator<nil> : iterator_base<cons_iterator<nil> >
|
|
{
|
|
typedef cons_iterator_tag tag;
|
|
typedef nil cons_type;
|
|
cons_iterator() {}
|
|
explicit cons_iterator(nil const&) {}
|
|
};
|
|
|
|
template <>
|
|
struct cons_iterator<nil const> : iterator_base<cons_iterator<nil const> >
|
|
{
|
|
typedef cons_iterator_tag tag;
|
|
typedef nil const cons_type;
|
|
cons_iterator() {}
|
|
explicit cons_iterator(nil const&) {}
|
|
};
|
|
|
|
struct nil : sequence_base<nil>
|
|
{
|
|
typedef cons_tag tag;
|
|
typedef void_t car_type;
|
|
typedef void_t cdr_type;
|
|
};
|
|
|
|
template <typename Car, typename Cdr = nil>
|
|
struct cons : sequence_base<cons<Car,Cdr> >
|
|
{
|
|
typedef cons_tag tag;
|
|
typedef typename call_traits<Car>::value_type car_type;
|
|
typedef Cdr cdr_type;
|
|
|
|
cons()
|
|
: car(), cdr() {}
|
|
|
|
explicit cons(
|
|
typename call_traits<Car>::param_type car_
|
|
, typename call_traits<Cdr>::param_type cdr_ = Cdr())
|
|
: car(car_), cdr(cdr_) {}
|
|
|
|
car_type car;
|
|
cdr_type cdr;
|
|
};
|
|
|
|
template <typename Car>
|
|
inline cons<Car>
|
|
make_cons(Car const& car)
|
|
{
|
|
return cons<Car>(car);
|
|
}
|
|
|
|
template <typename Car, typename Cdr>
|
|
inline cons<Car, Cdr>
|
|
make_cons(Car const& car, Cdr const& cdr)
|
|
{
|
|
return cons<Car, Cdr>(car, cdr);
|
|
}
|
|
}} // namespace boost::fusion
|
|
|
|
namespace boost { namespace mpl
|
|
{
|
|
template <typename Tag>
|
|
struct begin_impl;
|
|
|
|
template <typename Tag>
|
|
struct end_impl;
|
|
|
|
template <>
|
|
struct begin_impl<fusion::cons_tag>
|
|
: fusion::meta::begin_impl<fusion::cons_tag>
|
|
{
|
|
};
|
|
|
|
template <>
|
|
struct end_impl<fusion::cons_tag>
|
|
: fusion::meta::end_impl<fusion::cons_tag>
|
|
{
|
|
};
|
|
|
|
}} // namespace boost::mpl
|
|
|
|
#endif
|
|
|
|
// Before Boost v1.33.1, Fusion cons lists were not valid MPL sequences.
|
|
#if BOOST_VERSION < 103301
|
|
namespace boost { namespace mpl
|
|
{
|
|
template<typename Iterator>
|
|
struct next;
|
|
|
|
template<typename Cons>
|
|
struct next<fusion::cons_iterator<Cons> >
|
|
: fusion::cons_detail::next_traits_impl<fusion::cons_iterator<Cons> >
|
|
{
|
|
};
|
|
|
|
template<typename Iterator>
|
|
struct deref;
|
|
|
|
template<typename Cons>
|
|
struct deref<fusion::cons_iterator<Cons> >
|
|
: fusion::cons_detail::value_traits_impl<fusion::cons_iterator<Cons> >
|
|
{
|
|
};
|
|
|
|
}} // namespace boost::mpl
|
|
#endif
|
|
|
|
#endif
|