/usr/include/boost/yap/detail
Edit: /usr/include/boost/yap/detail/transform.hpp (21225B)
// Copyright (C) 2016-2018 T. Zachary Laine
//
// 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_YAP_DETAIL_TRANSFORM_HPP_INCLUDED
#define BOOST_YAP_DETAIL_TRANSFORM_HPP_INCLUDED
#include
#include
#include
namespace boost { namespace yap { namespace detail {
template
struct nth_element_impl
{
using type = typename nth_element_impl::type;
};
template
struct nth_element_impl<0, T, Ts...>
{
using type = T;
};
template
using nth_element = typename nth_element_impl::type;
template::value>
struct rvalue_ref_to_value;
template
struct rvalue_ref_to_value
{
using type = typename std::remove_reference::type;
};
template
struct rvalue_ref_to_value
{
using type = T;
};
template
using rvalue_ref_to_value_t = typename rvalue_ref_to_value::type;
template
struct rvalue_mover
{
template
constexpr decltype(auto) operator()(T && t) const
{
return static_cast(t);
}
};
template<>
struct rvalue_mover
{
template
constexpr std::remove_reference_t operator()(T && t) const
{
return std::move(t);
}
};
template
struct placeholder_transform_t
{
using tuple_t = hana::tuple...>;
constexpr placeholder_transform_t(PlaceholderArgs &&... args) :
placeholder_args_(static_cast(args)...)
{}
template
constexpr decltype(auto)
operator()(expr_tag, boost::yap::placeholder) const
{
static_assert(
I <= decltype(hana::size(std::declval()))::value,
"Out of range placeholder index,");
using nth_type = nth_element;
return as_expr(
rvalue_mover::value>{}(
placeholder_args_[hana::llong{}]));
}
tuple_t placeholder_args_;
};
template
struct evaluation_transform_t
{
using tuple_t = hana::tuple...>;
constexpr evaluation_transform_t(PlaceholderArgs &&... args) :
placeholder_args_(static_cast(args)...)
{}
template
constexpr decltype(auto)
operator()(expr_tag, boost::yap::placeholder) const
{
static_assert(
I <= decltype(hana::size(std::declval()))::value,
"Out of range placeholder index,");
using nth_type = nth_element;
return rvalue_mover::value>{}(
placeholder_args_[hana::llong{}]);
}
template
constexpr decltype(auto) operator()(expr_tag, T && t) const
{
return static_cast(t);
}
#define BOOST_YAP_UNARY_OPERATOR_CASE(op, op_name) \
template \
constexpr decltype(auto) operator()(expr_tag, T && t) const \
{ \
return op transform( \
as_expr(static_cast(t)), *this); \
}
BOOST_YAP_UNARY_OPERATOR_CASE(+, unary_plus)
BOOST_YAP_UNARY_OPERATOR_CASE(-, negate)
BOOST_YAP_UNARY_OPERATOR_CASE(*, dereference)
BOOST_YAP_UNARY_OPERATOR_CASE(~, complement)
BOOST_YAP_UNARY_OPERATOR_CASE(&, address_of)
BOOST_YAP_UNARY_OPERATOR_CASE(!, logical_not)
BOOST_YAP_UNARY_OPERATOR_CASE(++, pre_inc)
BOOST_YAP_UNARY_OPERATOR_CASE(--, pre_dec)
template
constexpr decltype(auto) operator()(expr_tag, T && t) const
{
return transform(
as_expr(static_cast(t)), *this)++;
}
template
constexpr decltype(auto) operator()(expr_tag, T && t) const
{
return transform(
as_expr(static_cast(t)), *this)--;
}
#undef BOOST_YAP_UNARY_OPERATOR_CASE
#define BOOST_YAP_BINARY_OPERATOR_CASE(op, op_name) \
template \
constexpr decltype(auto) operator()(expr_tag, T && t, U && u) const \
{ \
return transform(as_expr(static_cast(t)), *this) \
op transform(as_expr(static_cast(u)), *this); \
}
BOOST_YAP_BINARY_OPERATOR_CASE(<<, shift_left)
BOOST_YAP_BINARY_OPERATOR_CASE(>>, shift_right)
BOOST_YAP_BINARY_OPERATOR_CASE(*, multiplies)
BOOST_YAP_BINARY_OPERATOR_CASE(/, divides)
BOOST_YAP_BINARY_OPERATOR_CASE(%, modulus)
BOOST_YAP_BINARY_OPERATOR_CASE(+, plus)
BOOST_YAP_BINARY_OPERATOR_CASE(-, minus)
BOOST_YAP_BINARY_OPERATOR_CASE(<, less)
BOOST_YAP_BINARY_OPERATOR_CASE(>, greater)
BOOST_YAP_BINARY_OPERATOR_CASE(<=, less_equal)
BOOST_YAP_BINARY_OPERATOR_CASE(>=, greater_equal)
BOOST_YAP_BINARY_OPERATOR_CASE(==, equal_to)
BOOST_YAP_BINARY_OPERATOR_CASE(!=, not_equal_to)
BOOST_YAP_BINARY_OPERATOR_CASE(||, logical_or)
BOOST_YAP_BINARY_OPERATOR_CASE(&&, logical_and)
BOOST_YAP_BINARY_OPERATOR_CASE(&, bitwise_and)
BOOST_YAP_BINARY_OPERATOR_CASE(|, bitwise_or)
BOOST_YAP_BINARY_OPERATOR_CASE (^, bitwise_xor)
// clang-format off
//[ evaluation_transform_comma
template
constexpr decltype(auto) operator()(expr_tag, T && t, U && u) const
{
return transform(
as_expr(static_cast(t)), *this),
transform(
as_expr(static_cast(u)), *this);
}
//]
// clang-format on
BOOST_YAP_BINARY_OPERATOR_CASE(->*, mem_ptr)
BOOST_YAP_BINARY_OPERATOR_CASE(=, assign)
BOOST_YAP_BINARY_OPERATOR_CASE(<<=, shift_left_assign)
BOOST_YAP_BINARY_OPERATOR_CASE(>>=, shift_right_assign)
BOOST_YAP_BINARY_OPERATOR_CASE(*=, multiplies_assign)
BOOST_YAP_BINARY_OPERATOR_CASE(/=, divides_assign)
BOOST_YAP_BINARY_OPERATOR_CASE(%=, modulus_assign)
BOOST_YAP_BINARY_OPERATOR_CASE(+=, plus_assign)
BOOST_YAP_BINARY_OPERATOR_CASE(-=, minus_assign)
BOOST_YAP_BINARY_OPERATOR_CASE(&=, bitwise_and_assign)
BOOST_YAP_BINARY_OPERATOR_CASE(|=, bitwise_or_assign)
BOOST_YAP_BINARY_OPERATOR_CASE(^=, bitwise_xor_assign)
template
constexpr decltype(auto)
operator()(expr_tag, T && t, U && u) const
{
return transform(
as_expr(static_cast(t)), *this)[transform(
as_expr(static_cast(u)), *this)];
}
#undef BOOST_YAP_BINARY_OPERATOR_CASE
template
constexpr decltype(auto)
operator()(expr_tag, T && t, U && u, V && v) const
{
return transform(as_expr(static_cast(t)), *this)
? transform(
as_expr(static_cast(u)), *this)
: transform(
as_expr(static_cast(v)),
*this);
}
// clang-format off
//[ evaluation_transform_call
template
constexpr decltype(auto) operator()(
expr_tag, Callable && callable, Args &&... args) const
{
return transform(as_expr(static_cast(callable)), *this)(
transform(as_expr(static_cast(args)), *this)...
);
}
//]
// clang-format on
tuple_t placeholder_args_;
};
template
struct transform_impl;
template<
bool Strict,
typename Expr,
typename TransformTuple,
int I,
expr_arity Arity,
typename = void_t<>>
struct transform_expression_tag;
// Forward terminals/recurively transform noterminasl; attempted last.
template
struct default_transform
{
template
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
return static_cast(expr);
}
};
template
struct default_transform
{
struct incomplete;
// If you're getting an error because this function is uncallable,
// that's by design. You called yap::transform_strict(expr, xfrom)
// and one or more subexpression of 'expr' are not callable with any
// overload in 'xform'.
template
constexpr incomplete operator()(Expr && expr, TransformTuple transforms) const;
};
template<
expr_kind Kind,
template class ExprTemplate,
typename OldTuple,
typename NewTuple>
constexpr auto make_expr_from_tuple(
ExprTemplate const & expr, NewTuple && tuple)
{
return ExprTemplate{std::move(tuple)};
}
template
constexpr auto make_expr_from_tuple(Expr const & expr, NewTuple && tuple)
{
return minimal_expr{std::move(tuple)};
}
template
constexpr decltype(auto) transform_nonterminal(
Expr const & expr, Tuple && tuple, TransformTuple transforms)
{
auto transformed_tuple =
hana::transform(static_cast(tuple), [&](auto && element) {
using element_t = decltype(element);
auto const kind = remove_cv_ref_t::kind;
::boost::yap::detail::
transform_impl
xform;
return xform(static_cast(element), transforms);
});
auto const kind = remove_cv_ref_t::kind;
return make_expr_from_tuple(expr, std::move(transformed_tuple));
}
template<>
struct default_transform
{
template
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
return transform_nonterminal(expr, expr.elements, transforms);
}
};
template<>
struct default_transform
{
template
constexpr decltype(auto)
operator()(Expr && expr, TransformTuple transforms) const
{
return transform_nonterminal(
expr, std::move(expr.elements), transforms);
}
};
// Dispatch to the next transform, or to the default transform if there is
// no next transform.
template<
bool Strict,
typename Expr,
typename TransformTuple,
int I,
bool NextTransformExists>
struct next_or_default_transform
{
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
// Use the next transform.
constexpr expr_kind kind = remove_cv_ref_t::kind;
return detail::
transform_impl{}(
static_cast(expr), transforms);
}
};
template
struct next_or_default_transform
{
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
// No next transform exists; use the default transform.
constexpr expr_kind kind = remove_cv_ref_t::kind;
return default_transform<
std::is_lvalue_reference::value,
kind == expr_kind::terminal,
Strict>{}(static_cast(expr), transforms);
}
};
// Expression-matching; attempted second.
template<
bool Strict,
typename Expr,
typename TransformTuple,
int I,
typename = detail::void_t<>>
struct transform_expression_expr
{
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
// No expr-matching succeeded; use the next or default transform.
return next_or_default_transform<
Strict,
Expr,
TransformTuple,
I,
I + 1 < decltype(hana::size(
std::declval()))::value>{}(
static_cast(expr), transforms);
}
};
template
struct transform_expression_expr<
Strict,
Expr,
TransformTuple,
I,
void_t()[hana::llong{}])(
std::declval()))>>
{
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
return (*transforms[hana::llong{}])(static_cast(expr));
}
};
// Tag-matching; attempted first.
template<
bool Strict,
typename Expr,
typename TransformTuple,
int I,
expr_arity Arity,
typename>
struct transform_expression_tag
{
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
// No tag-matching succeeded; try expr-matching.
return transform_expression_expr{}(
static_cast(expr), transforms);
}
};
template
constexpr decltype(auto) terminal_value(T && x)
{
return value_impl(static_cast(x));
}
template
struct transform_expression_tag<
Strict,
Expr,
TransformTuple,
I,
expr_arity::one,
void_t()[hana::llong{}])(
expr_tag::kind>{},
terminal_value(::boost::yap::value(std::declval()))))>>
{
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
return (*transforms[hana::llong{}])(
expr_tag::kind>{},
terminal_value(
::boost::yap::value(static_cast(expr))));
}
};
template
struct transform_expression_tag<
Strict,
Expr,
TransformTuple,
I,
expr_arity::two,
void_t()[hana::llong{}])(
expr_tag::kind>{},
terminal_value(::boost::yap::left(std::declval())),
terminal_value(::boost::yap::right(std::declval()))))>>
{
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
return (*transforms[hana::llong{}])(
expr_tag::kind>{},
terminal_value(::boost::yap::left(static_cast(expr))),
terminal_value(
::boost::yap::right(static_cast(expr))));
}
};
template
struct transform_expression_tag<
Strict,
Expr,
TransformTuple,
I,
expr_arity::three,
void_t()[hana::llong{}])(
expr_tag::kind>{},
terminal_value(::boost::yap::cond(std::declval())),
terminal_value(::boost::yap::then(std::declval())),
terminal_value(::boost::yap::else_(std::declval()))))>>
{
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
return (*transforms[hana::llong{}])(
expr_tag::kind>{},
terminal_value(::boost::yap::cond(static_cast(expr))),
terminal_value(::boost::yap::then(static_cast(expr))),
terminal_value(
::boost::yap::else_(static_cast(expr))));
}
};
template
struct transform_call_unpacker
{
template
constexpr auto operator()(
Expr && expr,
Transform & transform,
std::integer_sequence) const
-> decltype(transform(
expr_tag{},
terminal_value(::boost::yap::get(
static_cast(expr), hana::llong_c))...))
{
return transform(
expr_tag{},
terminal_value(::boost::yap::get(
static_cast(expr), hana::llong_c))...);
}
};
template
constexpr auto indices_for(Expr const & expr)
{
constexpr long long size = decltype(hana::size(expr.elements))::value;
return std::make_integer_sequence();
}
template
struct transform_expression_tag<
Strict,
Expr,
TransformTuple,
I,
expr_arity::n,
void_t()[hana::llong{}])>{}(
std::declval(),
*std::declval()[hana::llong{}],
indices_for(std::declval())))>>
{
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
using transform_t = decltype(*transforms[hana::llong{}]);
return transform_call_unpacker{}(
static_cast(expr),
*transforms[hana::llong{}],
indices_for(expr));
}
};
template
struct transform_impl
{
template
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
constexpr expr_kind kind = detail::remove_cv_ref_t::kind;
return detail::transform_expression_tag<
Strict,
Expr,
TransformTuple,
I,
detail::arity_of()>{}(
static_cast(expr), transforms);
}
};
template
struct transform_impl
{
template
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
{
return detail::transform_impl{}(
::boost::yap::deref(static_cast(expr)), transforms);
}
};
}}}
#endif