Sprout/sprout/breed/traits.hpp

927 lines
27 KiB
C++
Raw Normal View History

#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>
>::type::type
};
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>
>::type::type
};
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