2012-02-08 14:39:36 +00:00
|
|
|
#ifndef SPROUT_BREED_TRAITS_HPP
|
|
|
|
#define SPROUT_BREED_TRAITS_HPP
|
|
|
|
|
|
|
|
#include <type_traits>
|
|
|
|
#include <sprout/config.hpp>
|
|
|
|
#include <sprout/utility/pack.hpp>
|
|
|
|
#include <sprout/tuple/tuple.hpp>
|
|
|
|
#include <sprout/breed/breed_fwd.hpp>
|
|
|
|
#include <sprout/breed/args.hpp>
|
|
|
|
#include <sprout/breed/domain.hpp>
|
|
|
|
#include <sprout/breed/transform/pass_through.hpp>
|
|
|
|
#include <sprout/breed/detail/template_arity.hpp>
|
|
|
|
|
|
|
|
namespace sprout {
|
|
|
|
namespace breed {
|
|
|
|
namespace detail {
|
|
|
|
template<typename T, typename Void = void>
|
|
|
|
struct if_vararg {};
|
|
|
|
template<typename T>
|
|
|
|
struct if_vararg<T, typename T::breed_is_vararg_>
|
|
|
|
: public T
|
|
|
|
{};
|
|
|
|
|
|
|
|
template<typename T, typename Void = void>
|
|
|
|
struct is_callable2_
|
|
|
|
: public std::false_type
|
|
|
|
{};
|
|
|
|
template<typename T>
|
|
|
|
struct is_callable2_<T, typename T::breed_is_callable_>
|
|
|
|
: public std::true_type
|
|
|
|
{};
|
|
|
|
template<typename T, long Arity = sprout::breed::detail::template_arity<T>::value>
|
|
|
|
struct is_callable_
|
|
|
|
: public sprout::breed::detail::is_callable2_<T>
|
|
|
|
{};
|
|
|
|
} // namespace detail
|
|
|
|
//
|
|
|
|
// is_callable
|
|
|
|
//
|
|
|
|
template<typename T>
|
|
|
|
struct is_callable
|
|
|
|
: public sprout::breed::detail::is_callable_<T>
|
|
|
|
{};
|
|
|
|
template<>
|
|
|
|
struct is_callable<sprout::breed::_>
|
|
|
|
: public std::true_type
|
|
|
|
{};
|
|
|
|
template<>
|
|
|
|
struct is_callable<sprout::breed::callable>
|
|
|
|
: public std::false_type
|
|
|
|
{};
|
|
|
|
template<typename PrimitiveTransform, typename X>
|
|
|
|
struct is_callable<sprout::breed::transform<PrimitiveTransform, X> >
|
|
|
|
: public std::false_type
|
|
|
|
{};
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<typename T, typename Void>
|
|
|
|
struct is_transform_
|
|
|
|
: public std::false_type
|
|
|
|
{};
|
|
|
|
template<typename T>
|
|
|
|
struct is_transform_<T, typename T::breed_is_transform_>
|
|
|
|
: public std::true_type
|
|
|
|
{};
|
|
|
|
} // namespace detail
|
|
|
|
//
|
|
|
|
// is_transform
|
|
|
|
//
|
|
|
|
template<typename T>
|
|
|
|
struct is_transform
|
|
|
|
: public sprout::breed::detail::is_transform_<T>
|
|
|
|
{};
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<typename T, typename Void>
|
|
|
|
struct is_aggregate_
|
|
|
|
: public std::is_pod<T>
|
|
|
|
{};
|
|
|
|
template<typename Tag, typename Args, long N>
|
|
|
|
struct is_aggregate_<sprout::breed::expr<Tag, Args, N>, void>
|
|
|
|
: public std::false_type
|
|
|
|
{};
|
|
|
|
template<typename Tag, typename Args, long N>
|
|
|
|
struct is_aggregate_<sprout::breed::basic_expr<Tag, Args, N>, void>
|
|
|
|
: public std::false_type
|
|
|
|
{};
|
|
|
|
template<typename T>
|
|
|
|
struct is_aggregate_<T, typename T::breed_is_aggregate_>
|
|
|
|
: public std::true_type
|
|
|
|
{};
|
|
|
|
} // namespace detail
|
|
|
|
//
|
|
|
|
// is_transform
|
|
|
|
//
|
|
|
|
template<typename T>
|
|
|
|
struct is_aggregate
|
|
|
|
: public sprout::breed::detail::is_aggregate_<T>
|
|
|
|
{};
|
|
|
|
|
|
|
|
//
|
|
|
|
// is_transform
|
|
|
|
//
|
|
|
|
template<typename T, typename Void>
|
|
|
|
struct is_expr
|
|
|
|
: public std::false_type
|
|
|
|
{};
|
|
|
|
template<typename T>
|
|
|
|
struct is_expr<T, typename T::breed_is_expr_>
|
|
|
|
: public std::true_type
|
|
|
|
{};
|
|
|
|
template<typename T>
|
|
|
|
struct is_expr<T&, void>
|
|
|
|
: public is_expr<T>
|
|
|
|
{};
|
|
|
|
|
|
|
|
//
|
|
|
|
// tag_of
|
|
|
|
//
|
|
|
|
template<typename Expr>
|
|
|
|
struct tag_of {
|
|
|
|
public:
|
|
|
|
typedef typename Expr::breed_tag type;
|
|
|
|
};
|
|
|
|
template<typename Expr>
|
|
|
|
struct tag_of<Expr&> {
|
|
|
|
public:
|
|
|
|
typedef typename Expr::breed_tag type;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// arity_of
|
|
|
|
//
|
|
|
|
template<typename Expr>
|
|
|
|
struct arity_of
|
|
|
|
: public Expr::breed_arity
|
|
|
|
{};
|
|
|
|
template<typename Expr>
|
|
|
|
struct arity_of<Expr&>
|
|
|
|
: public Expr::breed_arity
|
|
|
|
{};
|
|
|
|
|
|
|
|
namespace result_of {
|
|
|
|
//
|
|
|
|
// as_expr
|
|
|
|
//
|
|
|
|
template<typename T, typename Domain>
|
|
|
|
struct as_expr {
|
|
|
|
public:
|
|
|
|
typedef typename Domain::template as_expr<T>::result_type type;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// as_child
|
|
|
|
//
|
|
|
|
template<typename T, typename Domain>
|
|
|
|
struct as_child {
|
|
|
|
public:
|
|
|
|
typedef typename Domain::template as_child<T>::result_type type;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// child
|
|
|
|
//
|
|
|
|
template<typename Expr, typename N>
|
|
|
|
struct child
|
|
|
|
: public child_c<Expr, N::value>
|
|
|
|
{};
|
|
|
|
|
|
|
|
//
|
|
|
|
// value
|
|
|
|
//
|
|
|
|
template<typename Expr>
|
|
|
|
struct value {
|
|
|
|
static_assert(0 == Expr::breed_arity_c, "0 == Expr::breed_arity_c");
|
|
|
|
public:
|
|
|
|
typedef typename Expr::template breed_child<0>::type value_type;
|
|
|
|
typedef typename sprout::breed::detail::term_traits<value_type>::value_type type;
|
|
|
|
};
|
|
|
|
template<typename Expr>
|
|
|
|
struct value<Expr&> {
|
|
|
|
static_assert(0 == Expr::breed_arity_c, "0 == Expr::breed_arity_c");
|
|
|
|
public:
|
|
|
|
typedef typename Expr:template breed_child<0>::type value_type;
|
|
|
|
typedef typename sprout::breed::detail::term_traits<value_type>::reference type;
|
|
|
|
};
|
|
|
|
template<typename Expr>
|
|
|
|
struct value<Expr const&> {
|
|
|
|
static_assert(0 == Expr::breed_arity_c, "0 == Expr::breed_arity_c");
|
|
|
|
public:
|
|
|
|
typedef typename Expr:template breed_child<0>::type value_type;
|
|
|
|
typedef typename sprout::breed::detail::term_traits<value_type>::const_reference type;
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// left
|
|
|
|
//
|
|
|
|
template<typename Expr>
|
|
|
|
struct left
|
|
|
|
: public sprout::breed::result_of::child_c<Expr, 0>
|
|
|
|
{};
|
|
|
|
//
|
|
|
|
// right
|
|
|
|
//
|
|
|
|
template<typename Expr>
|
|
|
|
struct right
|
|
|
|
: public child_c<Expr, 1>
|
|
|
|
{};
|
|
|
|
} // namespace result_of
|
|
|
|
|
|
|
|
//
|
|
|
|
// terminal
|
|
|
|
//
|
|
|
|
template<typename T>
|
|
|
|
struct terminal
|
|
|
|
: public sprout::breed::transform<sprout::breed::terminal<T>, int>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef sprout::breed::tag::terminal breed_tag;
|
|
|
|
typedef sprout::breed::expr<sprout::breed::tag::terminal, sprout::breed::term<T>, 0> type;
|
|
|
|
typedef sprout::breed::basic_expr<sprout::breed::tag::terminal, sprout::breed::term<T>, 0> breed_grammar;
|
|
|
|
public:
|
|
|
|
template<long N>
|
|
|
|
struct breed_child
|
|
|
|
: public sprout::tppack_at<N, T>
|
|
|
|
{};
|
|
|
|
public:
|
|
|
|
template<typename Expr, typename State, typename Data>
|
|
|
|
struct impl
|
|
|
|
: public sprout::breed::transform_impl<Expr, State, Data>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef Expr result_type;
|
|
|
|
public:
|
|
|
|
#ifdef SPROUT_BREED_STRICT_RESULT_OF
|
|
|
|
SPROUT_CONSTEXPR result_type
|
|
|
|
#else
|
|
|
|
SPROUT_CONSTEXPR typename impl::expr_param
|
|
|
|
#endif
|
|
|
|
operator()(
|
|
|
|
typename impl::expr_param e,
|
|
|
|
typename impl::state_param,
|
|
|
|
typename impl::data_param
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// if_else_
|
|
|
|
//
|
|
|
|
template<typename T, typename U, typename V>
|
|
|
|
struct if_else_
|
|
|
|
: public sprout::breed::transform<if_else_<T, U, V>, int>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef sprout::breed::tag::if_else_ breed_tag;
|
|
|
|
typedef sprout::breed::expr<
|
|
|
|
sprout::breed::tag::if_else_, sprout::breed::sprout::breed::list<T, U, V>,
|
|
|
|
3
|
|
|
|
> type;
|
|
|
|
typedef sprout::breed::basic_expr<
|
|
|
|
sprout::breed::tag::if_else_,
|
|
|
|
sprout::breed::sprout::breed::list<T, U, V>,
|
|
|
|
3
|
|
|
|
> breed_grammar;
|
|
|
|
public:
|
|
|
|
template<long N>
|
|
|
|
struct breed_child
|
|
|
|
: public sprout::tppack_at<N, T, U, V>
|
|
|
|
{};
|
|
|
|
public:
|
|
|
|
template<typename Expr, typename State, typename Data>
|
|
|
|
struct impl
|
|
|
|
: public sprout::breed::detail::pass_through_impl<sprout::breed::if_else_, Expr, State, Data>
|
|
|
|
{};
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// nullary_expr
|
|
|
|
//
|
|
|
|
template<typename Tag, typename T>
|
|
|
|
struct nullary_expr
|
|
|
|
: public sprout::breed::transform<sprout::breed::nullary_expr<Tag, T>, int>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef Tag breed_tag;
|
|
|
|
typedef sprout::breed::expr<Tag, sprout::breed::term<T>, 0> type;
|
|
|
|
typedef sprout::breed::basic_expr<Tag, sprout::breed::term<T>, 0> breed_grammar;
|
|
|
|
public:
|
|
|
|
template<long N>
|
|
|
|
struct breed_child
|
|
|
|
: public sprout::tppack_at<N, T>
|
|
|
|
{};
|
|
|
|
public:
|
|
|
|
template<typename Expr, typename State, typename Data>
|
|
|
|
struct impl
|
|
|
|
: public sprout::breed::transform_impl<Expr, State, Data>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef Expr result_type;
|
|
|
|
public:
|
|
|
|
#ifdef SPROUT_BREED_STRICT_RESULT_OF
|
|
|
|
SPROUT_CONSTEXPR result_type
|
|
|
|
#else
|
|
|
|
SPROUT_CONSTEXPR typename impl::expr_param
|
|
|
|
#endif
|
|
|
|
operator()(
|
|
|
|
typename impl::expr_param e,
|
|
|
|
typename impl::state_param,
|
|
|
|
typename impl::data_param
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// unary_expr
|
|
|
|
//
|
|
|
|
template<typename Tag, typename T>
|
|
|
|
struct unary_expr
|
|
|
|
: public sprout::breed::transform<sprout::breed::unary_expr<Tag, T>, int>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef Tag breed_tag;
|
|
|
|
typedef sprout::breed::expr<Tag, sprout::breed::sprout::breed::list<T>, 1> type;
|
|
|
|
typedef sprout::breed::basic_expr<Tag, sprout::breed::sprout::breed::list<T>, 1> breed_grammar;
|
|
|
|
public:
|
|
|
|
template<long N>
|
|
|
|
struct breed_child
|
|
|
|
: public sprout::tppack_at<N, T>
|
|
|
|
{};
|
|
|
|
public:
|
|
|
|
template<typename Expr, typename State, typename Data>
|
|
|
|
struct impl
|
|
|
|
: public sprout::breed::detail::pass_through_impl<sprout::breed::unary_expr, Expr, State, Data>
|
|
|
|
{};
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// binary_expr
|
|
|
|
//
|
|
|
|
template<typename Tag, typename T, typename U>
|
|
|
|
struct binary_expr
|
|
|
|
: public sprout::breed::transform<sprout::breed::binary_expr<Tag, T, U>, int>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef Tag breed_tag;
|
|
|
|
typedef sprout::breed::expr<Tag, sprout::breed::list<T, U>, 2> type;
|
|
|
|
typedef sprout::breed::basic_expr<Tag, sprout::breed::list<T, U>, 2> breed_grammar;
|
|
|
|
public:
|
|
|
|
template<long N>
|
|
|
|
struct breed_child
|
|
|
|
: public sprout::tppack_at<N, T, U>
|
|
|
|
{};
|
|
|
|
public:
|
|
|
|
template<typename Expr, typename State, typename Data>
|
|
|
|
struct impl
|
|
|
|
: public sprout::breed::detail::pass_through_impl<binary_expr, Expr, State, Data>
|
|
|
|
{};
|
|
|
|
};
|
|
|
|
|
|
|
|
# define SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(op) \
|
|
|
|
template<typename T> \
|
|
|
|
struct op \
|
|
|
|
: public sprout::breed::transform<op<T>, int> \
|
|
|
|
{ \
|
|
|
|
public: \
|
|
|
|
typedef sprout::breed::tag::op breed_tag; \
|
|
|
|
typedef sprout::breed::expr<sprout::breed::tag::op, sprout::breed::list<T>, 1> type; \
|
|
|
|
typedef sprout::breed::basic_expr<sprout::breed::tag::op, sprout::breed::list<T>, 1> breed_grammar; \
|
|
|
|
public: \
|
|
|
|
template<long N> \
|
|
|
|
struct breed_child \
|
|
|
|
: public sprout::tppack_at<N, T> \
|
|
|
|
{}; \
|
|
|
|
public: \
|
|
|
|
template<typename Expr, typename State, typename Data> \
|
|
|
|
struct impl \
|
|
|
|
: public sprout::breed::detail::pass_through_impl<op, Expr, State, Data> \
|
|
|
|
{}; \
|
|
|
|
};
|
|
|
|
# define SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(op) \
|
|
|
|
template<typename T, typename U> \
|
|
|
|
struct op \
|
|
|
|
: public sprout::breed::transform<op<T, U>, int> \
|
|
|
|
{ \
|
|
|
|
public: \
|
|
|
|
typedef sprout::breed::tag::op breed_tag; \
|
|
|
|
typedef sprout::breed::expr<sprout::breed::tag::op, sprout::breed::list<T, U>, 2> type; \
|
|
|
|
typedef sprout::breed::basic_expr<sprout::breed::tag::op, sprout::breed::list<T, U>, 2> breed_grammar; \
|
|
|
|
public: \
|
|
|
|
template<long N> \
|
|
|
|
struct breed_child \
|
|
|
|
: public sprout::tppack_at<N, T, U> \
|
|
|
|
{}; \
|
|
|
|
public: \
|
|
|
|
template<typename Expr, typename State, typename Data> \
|
|
|
|
struct impl \
|
|
|
|
: public sprout::breed::detail::pass_through_impl<op, Expr, State, Data> \
|
|
|
|
{}; \
|
|
|
|
};
|
|
|
|
|
|
|
|
SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(unary_plus)
|
|
|
|
SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(negate)
|
|
|
|
SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(dereference)
|
|
|
|
SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(complement)
|
|
|
|
SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(address_of)
|
|
|
|
SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(logical_not)
|
|
|
|
SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(pre_inc)
|
|
|
|
SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(pre_dec)
|
|
|
|
SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(post_inc)
|
|
|
|
SPROUT_BREED_DEFINE_UNARY_METAFUNCTION(post_dec)
|
|
|
|
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_left)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_right)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(multiplies)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(divides)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(modulus)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(plus)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(minus)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(less)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(greater)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(less_equal)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(greater_equal)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(equal_to)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(not_equal_to)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(logical_or)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(logical_and)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_or)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_and)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_xor)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(comma)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(mem_ptr)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(assign)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_left_assign)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(shift_right_assign)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(multiplies_assign)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(divides_assign)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(modulus_assign)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(plus_assign)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(minus_assign)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_or_assign)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_and_assign)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(bitwise_xor_assign)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(subscript)
|
|
|
|
SPROUT_BREED_DEFINE_BINARY_METAFUNCTION(member)
|
|
|
|
|
|
|
|
# undef SPROUT_BREED_DEFINE_UNARY_METAFUNCTION
|
|
|
|
# undef SPROUT_BREED_DEFINE_BINARY_METAFUNCTION
|
|
|
|
|
|
|
|
//
|
|
|
|
// function
|
|
|
|
//
|
|
|
|
template<typename... Args>
|
|
|
|
struct function
|
|
|
|
: public sprout::breed::transform<
|
|
|
|
sprout::breed::function<Args...>,
|
|
|
|
int
|
|
|
|
>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef sprout::breed::tag::function breed_tag;
|
|
|
|
typedef sprout::breed::expr<
|
|
|
|
sprout::breed::tag::function, sprout::breed::list<Args...>,
|
|
|
|
sizeof...(Args)
|
|
|
|
> type;
|
|
|
|
typedef sprout::breed::basic_expr<
|
|
|
|
sprout::breed::tag::function, sprout::breed::list<Args...>,
|
|
|
|
sizeof...(Args)
|
|
|
|
> breed_grammar;
|
|
|
|
public:
|
|
|
|
template<long N>
|
|
|
|
struct breed_child {
|
|
|
|
public:
|
|
|
|
typedef std::conditional<
|
|
|
|
N < sizeof...(Args),
|
|
|
|
sprout::tppack_at<N, Args...>,
|
|
|
|
sprout::breed::detail::if_vararg<typename sprout::tppack_at<sizeof...(Args) - 1, Args...>::type>
|
2012-05-21 16:06:13 +00:00
|
|
|
>::type::type
|
2012-02-08 14:39:36 +00:00
|
|
|
};
|
|
|
|
template<typename Expr, typename State, typename Data>
|
|
|
|
struct impl
|
|
|
|
: public sprout::breed::detail::pass_through_impl<function, Expr, State, Data>
|
|
|
|
{};
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// nary_expr
|
|
|
|
//
|
|
|
|
template<typename Tag, typename... Args>
|
|
|
|
struct nary_expr
|
|
|
|
: public sprout::breed::transform<
|
|
|
|
sprout::breed::nary_expr<Tag, Args...>,
|
|
|
|
int
|
|
|
|
>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef Tag breed_tag;
|
|
|
|
typedef sprout::breed::expr<
|
|
|
|
Tag,
|
|
|
|
sprout::breed::list<Args...>,
|
|
|
|
sizeof...(Args)
|
|
|
|
> type;
|
|
|
|
typedef sprout::breed::basic_expr<
|
|
|
|
Tag,
|
|
|
|
sprout::breed::list<Args...>,
|
|
|
|
sizeof...(Args)
|
|
|
|
> breed_grammar;
|
|
|
|
public:
|
|
|
|
template<long N>
|
|
|
|
struct breed_child {
|
|
|
|
public:
|
|
|
|
typedef std::conditional<
|
|
|
|
N < sizeof...(Args),
|
|
|
|
sprout::tppack_at<N, Args...>,
|
|
|
|
sprout::breed::detail::if_vararg<typename sprout::tppack_at<sizeof...(Args) - 1, Args...>::type>
|
2012-05-21 16:06:13 +00:00
|
|
|
>::type::type
|
2012-02-08 14:39:36 +00:00
|
|
|
};
|
|
|
|
template<typename Expr, typename State, typename Data>
|
|
|
|
struct impl
|
|
|
|
: public sprout::breed::detail::pass_through_impl<sprout::breed::nary_expr, Expr, State, Data>
|
|
|
|
{};
|
|
|
|
};
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
template<template<typename...> class T, typename... Args>
|
|
|
|
struct is_callable_<T<Args...>, sizeof...(Args)>
|
|
|
|
: public std::is_same<
|
|
|
|
typename sprout::tppack_at<sizeof...(Args) - 1, Args...>::type,
|
|
|
|
sprout::breed::callable
|
|
|
|
>
|
|
|
|
{};
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
namespace result_of {
|
|
|
|
//
|
|
|
|
// child_c
|
|
|
|
//
|
|
|
|
template<typename Expr, long N>
|
|
|
|
struct child_c {
|
|
|
|
static_assert(0 != Expr::proto_arity_c, "0 != Expr::proto_arity_c");
|
|
|
|
public:
|
|
|
|
typedef typename Expr::template breed_child<N>::type value_type;
|
|
|
|
typedef typename sprout::breed::detail::expr_traits<value_type>::value_type type;
|
|
|
|
};
|
|
|
|
template<typename Expr, long N>
|
|
|
|
struct child_c<Expr&, N> {
|
|
|
|
static_assert(0 != Expr::proto_arity_c, "0 != Expr::proto_arity_c");
|
|
|
|
public:
|
|
|
|
typedef typename Expr::template breed_child<N>::type value_type;
|
|
|
|
typedef typename detail::expr_traits<value_type>::reference type;
|
|
|
|
public:
|
|
|
|
static type call(Expr& e) {
|
|
|
|
return e.proto_base().breed child<N>();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
template<typename Expr, long N>
|
|
|
|
struct child_c<Expr const&, N> {
|
|
|
|
static_assert(0 != Expr::proto_arity_c, "0 != Expr::proto_arity_c");
|
|
|
|
public:
|
|
|
|
typedef typename Expr::template breed_child<N>::type value_type;
|
|
|
|
typedef typename detail::expr_traits<value_type>::const_reference type;
|
|
|
|
public:
|
|
|
|
static SPROUT_CONSTEXPR type call(Expr const& e) {
|
|
|
|
return e.proto_base().breed child<N>();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace result_of
|
|
|
|
|
|
|
|
namespace functional {
|
|
|
|
//
|
|
|
|
// as_expr
|
|
|
|
//
|
|
|
|
template<typename Domain>
|
|
|
|
struct as_expr {
|
|
|
|
public:
|
|
|
|
SPROUT_BREED_CALLABLE()
|
|
|
|
public:
|
|
|
|
template<typename Sig>
|
|
|
|
struct result;
|
|
|
|
template<typename This, typename T>
|
|
|
|
struct result<This(T)> {
|
|
|
|
typedef typename Domain::template as_expr<T>::result_type type;
|
|
|
|
};
|
|
|
|
template<typename This, typename T>
|
|
|
|
struct result<This(T&)> {
|
|
|
|
typedef typename Domain::template as_expr<T>::result_type type;
|
|
|
|
};
|
|
|
|
public:
|
|
|
|
template<typename T>
|
|
|
|
SPROUT_CONSTEXPR typename std::add_const<
|
|
|
|
typename result<sprout::breed::as_expr(T const&)>::type
|
|
|
|
>::type operator()(T const& t) const {
|
|
|
|
return typename Domain::template as_expr<T const>()(t);
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
|
|
typename std::add_const<
|
|
|
|
typename result<sprout::breed::as_expr(T&)>::type
|
|
|
|
>::type operator()(T& t) const {
|
|
|
|
return typename Domain::template as_expr<T>()(t);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// as_child
|
|
|
|
//
|
|
|
|
template<typename Domain>
|
|
|
|
struct as_child {
|
|
|
|
public:
|
|
|
|
SPROUT_BREED_CALLABLE()
|
|
|
|
public:
|
|
|
|
template<typename Sig>
|
|
|
|
struct result;
|
|
|
|
template<typename This, typename T>
|
|
|
|
struct result<This(T)> {
|
|
|
|
public:
|
|
|
|
typedef typename Domain::template as_child<T>::result_type type;
|
|
|
|
};
|
|
|
|
template<typename This, typename T>
|
|
|
|
struct result<This(T&)> {
|
|
|
|
public:
|
|
|
|
typedef typename Domain::template as_child<T>::result_type type;
|
|
|
|
};
|
|
|
|
public:
|
|
|
|
template<typename T>
|
|
|
|
SPROUT_CONSTEXPR typename std::add_const<
|
|
|
|
typename result<as_child(T const&)>::type
|
|
|
|
>::type operator()(T const& t) const {
|
|
|
|
return typename Domain::template as_child<T const>()(t);
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
|
|
typename std::add_const<
|
|
|
|
typename result<as_child(T&)>::type
|
|
|
|
>::type operator()(T& t) const {
|
|
|
|
return typename Domain::template as_child<T const>()(t);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// child_c
|
|
|
|
//
|
|
|
|
template<long N>
|
|
|
|
struct child_c {
|
|
|
|
public:
|
|
|
|
SPROUT_BREED_CALLABLE()
|
|
|
|
public:
|
|
|
|
template<typename Sig>
|
|
|
|
struct result;
|
|
|
|
template<typename This, typename Expr>
|
|
|
|
struct result<This(Expr)> {
|
|
|
|
public:
|
|
|
|
typedef typename result_of::child_c<Expr, N>::type type;
|
|
|
|
};
|
|
|
|
public:
|
|
|
|
template<typename Expr>
|
|
|
|
SPROUT_CONSTEXPR typename result_of::child_c<Expr const&, N>::type operator()(Expr const& e) const {
|
|
|
|
return result_of::child_c<Expr const&, N>::call(e);
|
|
|
|
}
|
|
|
|
template<typename Expr>
|
|
|
|
typename result_of::child_c<Expr const&, N>::type operator()(Expr& e) const {
|
|
|
|
return result_of::child_c<Expr&, N>::call(e);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// child
|
|
|
|
//
|
|
|
|
template<typename N>
|
|
|
|
struct child {
|
|
|
|
public:
|
|
|
|
SPROUT_BREED_CALLABLE()
|
|
|
|
public:
|
|
|
|
template<typename Sig>
|
|
|
|
struct result;
|
|
|
|
template<typename This, typename Expr>
|
|
|
|
struct result<This(Expr)> {
|
|
|
|
public:
|
|
|
|
typedef typename result_of::child<Expr, N>::type type;
|
|
|
|
};
|
|
|
|
public:
|
|
|
|
template<typename Expr>
|
|
|
|
SPROUT_CONSTEXPR typename result_of::child<Expr const&, N>::type operator()(Expr const& e) const {
|
|
|
|
return result_of::child<Expr const&, N>::call(e);
|
|
|
|
}
|
|
|
|
template<typename Expr>
|
|
|
|
typename result_of::child<Expr&, N>::type operator()(Expr const& e) const {
|
|
|
|
return result_of::child<Expr&, N>::call(e);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// value
|
|
|
|
//
|
|
|
|
struct value {
|
|
|
|
public:
|
|
|
|
SPROUT_BREED_CALLABLE()
|
|
|
|
public:
|
|
|
|
template<typename Sig>
|
|
|
|
struct result;
|
|
|
|
template<typename This, typename Expr>
|
|
|
|
struct result<This(Expr)> {
|
|
|
|
public:
|
|
|
|
typedef typename result_of::value<Expr>::type type;
|
|
|
|
};
|
|
|
|
public:
|
|
|
|
template<typename Expr>
|
|
|
|
SPROUT_CONSTEXPR typename result_of::value<Expr const&>::type operator()(Expr const& e) const {
|
|
|
|
return e.breed_base().template child<0>();
|
|
|
|
}
|
|
|
|
template<typename Expr>
|
|
|
|
typename result_of::value<Expr&>::type operator()(Expr& e) const {
|
|
|
|
return e.breed_base().template child<0>();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// left
|
|
|
|
//
|
|
|
|
struct left {
|
|
|
|
public:
|
|
|
|
SPROUT_BREED_CALLABLE()
|
|
|
|
public:
|
|
|
|
template<typename Sig>
|
|
|
|
struct result;
|
|
|
|
template<typename This, typename Expr>
|
|
|
|
struct result<This(Expr)> {
|
|
|
|
public:
|
|
|
|
typedef typename result_of::left<Expr>::type type;
|
|
|
|
};
|
|
|
|
public:
|
|
|
|
template<typename Expr>
|
|
|
|
SPROUT_CONSTEXPR typename result_of::value<Expr const&>::type operator()(Expr const& e) const {
|
|
|
|
return e.breed_base().template child<0>();
|
|
|
|
}
|
|
|
|
template<typename Expr>
|
|
|
|
typename result_of::value<Expr&>::type operator()(Expr& e) const {
|
|
|
|
return e.breed_base().template child<0>();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// right
|
|
|
|
//
|
|
|
|
struct right {
|
|
|
|
public:
|
|
|
|
SPROUT_BREED_CALLABLE()
|
|
|
|
public:
|
|
|
|
template<typename Sig>
|
|
|
|
struct result;
|
|
|
|
template<typename This, typename Expr>
|
|
|
|
struct result<This(Expr)> {
|
|
|
|
public:
|
|
|
|
typedef typename result_of::right<Expr>::type type;
|
|
|
|
};
|
|
|
|
public:
|
|
|
|
template<typename Expr>
|
|
|
|
SPROUT_CONSTEXPR typename result_of::value<Expr const&>::type operator()(Expr const& e) const {
|
|
|
|
return e.breed_base().template child<1>();
|
|
|
|
}
|
|
|
|
template<typename Expr>
|
|
|
|
typename result_of::value<Expr&>::type operator()(Expr& e) const {
|
|
|
|
return e.breed_base().template child<1>();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace functional
|
|
|
|
|
|
|
|
//
|
|
|
|
// as_expr
|
|
|
|
//
|
|
|
|
template<typename T>
|
|
|
|
SPROUT_CONSTEXPR typename std::add_const<
|
|
|
|
typename sprout::breed::result_of::as_expr<T const, sprout::breed::default_domain>::type
|
|
|
|
>::type as_expr(T const& t) {
|
|
|
|
return sprout::breed::default_domain::as_expr<T const>()(t);
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
|
|
typename std::add_const<
|
|
|
|
typename sprout::breed::result_of::as_expr<T, sprout::breed::default_domain>::type
|
|
|
|
>::type as_expr(T& t) {
|
|
|
|
return sprout::breed::default_domain::as_expr<T>()(t);
|
|
|
|
}
|
|
|
|
template<typename Domain, typename T>
|
|
|
|
SPROUT_CONSTEXPR typename std::add_const<
|
|
|
|
typename sprout::breed::result_of::as_expr<T const, Domain>::type
|
|
|
|
>::type as_expr(T const& t) {
|
|
|
|
return typename Domain::template as_expr<T const>()(t);
|
|
|
|
}
|
|
|
|
template<typename Domain, typename T>
|
|
|
|
typename std::add_const<
|
|
|
|
typename sprout::breed::result_of::as_expr<T, Domain>::type
|
|
|
|
>::type as_expr(T& t) {
|
|
|
|
return typename Domain::template as_expr<T>()(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// as_child
|
|
|
|
//
|
|
|
|
template<typename T>
|
|
|
|
SPROUT_CONSTEXPR typename std::add_const<
|
|
|
|
typename sprout::breed::result_of::as_child<T const, sprout::breed::default_domain>::type
|
|
|
|
>::type as_child(T const& t)
|
|
|
|
{
|
|
|
|
return sprout::breed::default_domain::as_child<T const>()(t);
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
|
|
typename std::add_const<
|
|
|
|
typename sprout::breed::result_of::as_child<T, sprout::breed::default_domain>::type
|
|
|
|
>::type as_child(T& t)
|
|
|
|
{
|
|
|
|
return sprout::breed::default_domain::as_child<T>()(t);
|
|
|
|
}
|
|
|
|
template<typename Domain, typename T>
|
|
|
|
SPROUT_CONSTEXPR typename std::add_const<
|
|
|
|
typename sprout::breed::result_of::as_child<T const, Domain>::type
|
|
|
|
>::type as_child(T const& t)
|
|
|
|
{
|
|
|
|
return typename Domain::template as_child<T const>()(t);
|
|
|
|
}
|
|
|
|
template<typename Domain, typename T>
|
|
|
|
typename std::add_const<
|
|
|
|
typename sprout::breed::result_of::as_child<T, Domain>::type
|
|
|
|
>::type as_child(T& t)
|
|
|
|
{
|
|
|
|
return typename Domain::template as_child<T>()(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// child
|
|
|
|
//
|
|
|
|
template<typename N, typename Expr>
|
|
|
|
SPROUT_CONSTEXPR typename sprout::breed::result_of::child<Expr const&, N>::type child(Expr const& e) {
|
|
|
|
return sprout::breed::result_of::child<Expr const&, N>::call(e);
|
|
|
|
}
|
|
|
|
template<typename N, typename Expr>
|
|
|
|
typename sprout::breed::result_of::child<Expr&, N>::type child(Expr& e) {
|
|
|
|
return sprout::breed::result_of::child<Expr&, N>::call(e);
|
|
|
|
}
|
|
|
|
template<typename Expr2>
|
|
|
|
SPROUT_CONSTEXPR typename sprout::breed::detail::expr_traits<
|
|
|
|
typename Expr2::breed_base_expr:template breed_child<0>::type
|
|
|
|
>::const_reference child(Expr2 const& expr2) {
|
|
|
|
return expr2.breed_base().template child<0>();
|
|
|
|
}
|
|
|
|
template<typename Expr2>
|
|
|
|
typename sprout::breed::detail::expr_traits<
|
|
|
|
typename Expr2::breed_base_expr:template breed_child<0>::type
|
|
|
|
>::reference child(Expr2& expr2) {
|
|
|
|
return expr2.breed_base().template child<0>();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// child_c
|
|
|
|
//
|
|
|
|
template<long N, typename Expr>
|
|
|
|
SPROUT_CONSTEXPR typename sprout::breed::result_of::child_c<Expr const&, N>::type child_c(Expr const& e) {
|
|
|
|
return sprout::breed::result_of::child_c<Expr const&, N>::call(e);
|
|
|
|
}
|
|
|
|
template<long N, typename Expr>
|
|
|
|
typename sprout::breed::result_of::child_c<Expr&, N>::type child_c(Expr& e) {
|
|
|
|
return sprout::breed::result_of::child_c<Expr&, N>::call(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// value
|
|
|
|
//
|
|
|
|
template<typename Expr>
|
|
|
|
SPROUT_CONSTEXPR typename sprout::breed::result_of::value<Expr const&>::type value(Expr const& e) {
|
|
|
|
return e.breed_base().template child<0>();
|
|
|
|
}
|
|
|
|
template<typename Expr>
|
|
|
|
typename sprout::breed::result_of::value<Expr&>::type value(Expr& e) {
|
|
|
|
return e.breed_base().template child<0>();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// left
|
|
|
|
//
|
|
|
|
template<typename Expr>
|
|
|
|
SPROUT_CONSTEXPR typename sprout::breed::result_of::left<Expr const&>::type left(Expr const& e) {
|
|
|
|
return e.breed_base().template child<0>();
|
|
|
|
}
|
|
|
|
template<typename Expr>
|
|
|
|
typename sprout::breed::result_of::left<Expr&>::type left(Expr& e) {
|
|
|
|
return e.breed_base().template child<0>();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// right
|
|
|
|
//
|
|
|
|
template<typename Expr>
|
|
|
|
SPROUT_CONSTEXPR typename sprout::breed::result_of::right<Expr const&>::type right(Expr const& e) {
|
|
|
|
return e.breed_base().template child<1>();
|
|
|
|
}
|
|
|
|
template<typename Expr>
|
|
|
|
typename sprout::breed::result_of::right<Expr&>::type right(Expr& e) {
|
|
|
|
return e.breed_base().template child<1>();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// is_callable
|
|
|
|
//
|
|
|
|
template<typename Domain>
|
|
|
|
struct is_callable<sprout::breed::functional::as_expr<Domain> >
|
|
|
|
: public std::true_type
|
|
|
|
{};
|
|
|
|
template<typename Domain>
|
|
|
|
struct is_callable<sprout::breed::functional::as_child<Domain> >
|
|
|
|
: public std::true_type
|
|
|
|
{};
|
|
|
|
template<long N>
|
|
|
|
struct is_callable<sprout::breed::functional::child_c<N> >
|
|
|
|
: public std::true_type
|
|
|
|
{};
|
|
|
|
template<typename N>
|
|
|
|
struct is_callable<sprout::breed::functional::child<N> >
|
|
|
|
: public std::true_type
|
|
|
|
{};
|
|
|
|
} // namespace breed
|
|
|
|
} // namespace sprout
|
|
|
|
|
|
|
|
#endif // #ifndef SPROUT_BREED_TRAITS_HPP
|