feat():initial version
This commit is contained in:
736
install/boost_1_75_0/include/boost/yap/algorithm.hpp
Normal file
736
install/boost_1_75_0/include/boost/yap/algorithm.hpp
Normal file
@@ -0,0 +1,736 @@
|
||||
// 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_ALGORITHM_HPP_INCLUDED
|
||||
#define BOOST_YAP_ALGORITHM_HPP_INCLUDED
|
||||
|
||||
#include <boost/yap/algorithm_fwd.hpp>
|
||||
#include <boost/yap/user_macros.hpp>
|
||||
#include <boost/yap/detail/algorithm.hpp>
|
||||
|
||||
#include <boost/hana/size.hpp>
|
||||
#include <boost/hana/comparing.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace yap {
|
||||
|
||||
#ifdef BOOST_NO_CONSTEXPR_IF
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename Expr, bool MutableRvalueRef>
|
||||
struct deref_impl
|
||||
{
|
||||
constexpr decltype(auto) operator()(Expr && expr)
|
||||
{
|
||||
return std::move(*expr.elements[hana::llong_c<0>]);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Expr>
|
||||
struct deref_impl<Expr, false>
|
||||
{
|
||||
constexpr decltype(auto) operator()(Expr && expr)
|
||||
{
|
||||
return *expr.elements[hana::llong_c<0>];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** "Dereferences" a reference-expression, forwarding its referent to
|
||||
the caller. */
|
||||
template<typename Expr>
|
||||
constexpr decltype(auto) deref(Expr && expr)
|
||||
{
|
||||
static_assert(
|
||||
is_expr<Expr>::value, "deref() is only defined for expressions.");
|
||||
|
||||
static_assert(
|
||||
detail::remove_cv_ref_t<Expr>::kind == expr_kind::expr_ref,
|
||||
"deref() is only defined for expr_ref-kind expressions.");
|
||||
|
||||
#ifdef BOOST_NO_CONSTEXPR_IF
|
||||
return detail::deref_impl < Expr,
|
||||
std::is_rvalue_reference<Expr>::value &&
|
||||
!std::is_const<std::remove_reference_t<Expr>>::value >
|
||||
{}(static_cast<Expr &&>(expr));
|
||||
#else
|
||||
using namespace hana::literals;
|
||||
if constexpr (
|
||||
std::is_rvalue_reference<Expr>::value &&
|
||||
!std::is_const<std::remove_reference_t<Expr>>::value) {
|
||||
return std::move(*expr.elements[0_c]);
|
||||
} else {
|
||||
return *expr.elements[0_c];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename Tuple, long long I>
|
||||
struct lvalue_ref_ith_element
|
||||
: std::is_lvalue_reference<decltype(
|
||||
std::declval<Tuple>()[hana::llong<I>{}])>
|
||||
{
|
||||
};
|
||||
|
||||
#ifdef BOOST_NO_CONSTEXPR_IF
|
||||
|
||||
template<bool ValueOfTerminalsOnly, typename T>
|
||||
constexpr decltype(auto) value_impl(T && x);
|
||||
|
||||
template<
|
||||
typename T,
|
||||
bool IsExprRef,
|
||||
bool ValueOfTerminalsOnly,
|
||||
bool TakeValue,
|
||||
bool IsLvalueRef>
|
||||
struct value_expr_impl;
|
||||
|
||||
template<
|
||||
typename T,
|
||||
bool ValueOfTerminalsOnly,
|
||||
bool TakeValue,
|
||||
bool IsLvalueRef>
|
||||
struct value_expr_impl<
|
||||
T,
|
||||
true,
|
||||
ValueOfTerminalsOnly,
|
||||
TakeValue,
|
||||
IsLvalueRef>
|
||||
{
|
||||
constexpr decltype(auto) operator()(T && x)
|
||||
{
|
||||
return ::boost::yap::detail::value_impl<ValueOfTerminalsOnly>(
|
||||
::boost::yap::deref(static_cast<T &&>(x)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bool ValueOfTerminalsOnly>
|
||||
struct value_expr_impl<T, false, ValueOfTerminalsOnly, true, true>
|
||||
{
|
||||
constexpr decltype(auto) operator()(T && x)
|
||||
{
|
||||
return x.elements[hana::llong_c<0>];
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bool ValueOfTerminalsOnly>
|
||||
struct value_expr_impl<T, false, ValueOfTerminalsOnly, true, false>
|
||||
{
|
||||
constexpr decltype(auto) operator()(T && x)
|
||||
{
|
||||
return std::move(x.elements[hana::llong_c<0>]);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bool ValueOfTerminalsOnly, bool IsLvalueRef>
|
||||
struct value_expr_impl<
|
||||
T,
|
||||
false,
|
||||
ValueOfTerminalsOnly,
|
||||
false,
|
||||
IsLvalueRef>
|
||||
{
|
||||
constexpr decltype(auto) operator()(T && x)
|
||||
{
|
||||
return static_cast<T &&>(x);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bool IsExpr, bool ValueOfTerminalsOnly>
|
||||
struct value_impl_t
|
||||
{
|
||||
constexpr decltype(auto) operator()(T && x)
|
||||
{
|
||||
constexpr expr_kind kind = detail::remove_cv_ref_t<T>::kind;
|
||||
constexpr detail::expr_arity arity = detail::arity_of<kind>();
|
||||
return value_expr_impl < T, kind == expr_kind::expr_ref,
|
||||
ValueOfTerminalsOnly,
|
||||
(ValueOfTerminalsOnly && kind == expr_kind::terminal) ||
|
||||
(!ValueOfTerminalsOnly &&
|
||||
arity == detail::expr_arity::one),
|
||||
std::is_lvalue_reference<T>::value ||
|
||||
detail::lvalue_ref_ith_element<
|
||||
decltype(x.elements),
|
||||
0>::value > {}(static_cast<T &&>(x));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bool ValueOfTerminalsOnly>
|
||||
struct value_impl_t<T, false, ValueOfTerminalsOnly>
|
||||
{
|
||||
constexpr decltype(auto) operator()(T && x)
|
||||
{
|
||||
return static_cast<T &&>(x);
|
||||
}
|
||||
};
|
||||
|
||||
template<bool ValueOfTerminalsOnly, typename T>
|
||||
constexpr decltype(auto) value_impl(T && x)
|
||||
{
|
||||
return detail::
|
||||
value_impl_t<T, is_expr<T>::value, ValueOfTerminalsOnly>{}(
|
||||
static_cast<T &&>(x));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<bool ValueOfTerminalsOnly, typename T>
|
||||
constexpr decltype(auto) value_impl(T && x)
|
||||
{
|
||||
if constexpr (is_expr<T>::value) {
|
||||
using namespace hana::literals;
|
||||
constexpr expr_kind kind = remove_cv_ref_t<T>::kind;
|
||||
constexpr expr_arity arity = arity_of<kind>();
|
||||
if constexpr (kind == expr_kind::expr_ref) {
|
||||
return value_impl<ValueOfTerminalsOnly>(
|
||||
::boost::yap::deref(static_cast<T &&>(x)));
|
||||
} else if constexpr (
|
||||
kind == expr_kind::terminal ||
|
||||
(!ValueOfTerminalsOnly && arity == expr_arity::one)) {
|
||||
if constexpr (
|
||||
std::is_lvalue_reference<T>::value ||
|
||||
detail::
|
||||
lvalue_ref_ith_element<decltype(x.elements), 0>{}) {
|
||||
return x.elements[0_c];
|
||||
} else {
|
||||
return std::move(x.elements[0_c]);
|
||||
}
|
||||
} else {
|
||||
return static_cast<T &&>(x);
|
||||
}
|
||||
} else {
|
||||
return static_cast<T &&>(x);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Forwards the sole element of \a x to the caller, possibly calling
|
||||
<code>deref()</code> first if \a x is a reference expression, or
|
||||
forwards \a x to the caller unchanged.
|
||||
|
||||
More formally:
|
||||
|
||||
- If \a x is not an expression, \a x is forwarded to the caller.
|
||||
|
||||
- Otherwise, if \a x is a reference expression, the result is
|
||||
<code>value(deref(x))</code>.
|
||||
|
||||
- Otherwise, if \a x is an expression with only one value (a unary
|
||||
expression or a terminal expression), the result is the forwarded
|
||||
first element of \a x.
|
||||
|
||||
- Otherwise, \a x is forwarded to the caller. */
|
||||
template<typename T>
|
||||
constexpr decltype(auto) value(T && x)
|
||||
{
|
||||
return detail::value_impl<false>(static_cast<T &&>(x));
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_CONSTEXPR_IF
|
||||
|
||||
template<typename Expr, typename I>
|
||||
constexpr decltype(auto) get(Expr && expr, I const & i);
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<long long I, typename Expr, bool IsExpr, bool IsLvalueRef>
|
||||
struct get_impl;
|
||||
|
||||
template<long long I, typename Expr, bool IsLvalueRef>
|
||||
struct get_impl<I, Expr, true, IsLvalueRef>
|
||||
{
|
||||
constexpr decltype(auto) operator()(Expr && expr, hana::llong<I> i)
|
||||
{
|
||||
return ::boost::yap::get(
|
||||
::boost::yap::deref(static_cast<Expr &&>(expr)), i);
|
||||
}
|
||||
};
|
||||
|
||||
template<long long I, typename Expr>
|
||||
struct get_impl<I, Expr, false, true>
|
||||
{
|
||||
constexpr decltype(auto) operator()(Expr && expr, hana::llong<I> i)
|
||||
{
|
||||
return expr.elements[i];
|
||||
}
|
||||
};
|
||||
|
||||
template<long long I, typename Expr>
|
||||
struct get_impl<I, Expr, false, false>
|
||||
{
|
||||
constexpr decltype(auto) operator()(Expr && expr, hana::llong<I> i)
|
||||
{
|
||||
return std::move(expr.elements[i]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** Forwards the <i>i</i>-th element of \a expr to the caller. If \a
|
||||
expr is a reference expression, the result is <code>get(deref(expr),
|
||||
i)</code>.
|
||||
|
||||
\note <code>get()</code> is only valid if \a Expr is an expression.
|
||||
*/
|
||||
template<typename Expr, typename I>
|
||||
constexpr decltype(auto) get(Expr && expr, I const & i)
|
||||
{
|
||||
static_assert(
|
||||
is_expr<Expr>::value, "get() is only defined for expressions.");
|
||||
static_assert(
|
||||
hana::IntegralConstant<I>::value,
|
||||
"'i' must be an IntegralConstant");
|
||||
|
||||
constexpr expr_kind kind = detail::remove_cv_ref_t<Expr>::kind;
|
||||
|
||||
static_assert(
|
||||
kind == expr_kind::expr_ref ||
|
||||
(0 <= I::value &&
|
||||
I::value < decltype(hana::size(expr.elements))::value),
|
||||
"In get(expr, I), I must be a valid index into expr's tuple "
|
||||
"elements.");
|
||||
|
||||
#ifdef BOOST_NO_CONSTEXPR_IF
|
||||
return detail::get_impl<
|
||||
I::value,
|
||||
Expr,
|
||||
kind == expr_kind::expr_ref,
|
||||
std::is_lvalue_reference<Expr>::value>{}(static_cast<Expr &&>(expr), i);
|
||||
#else
|
||||
using namespace hana::literals;
|
||||
if constexpr (kind == expr_kind::expr_ref) {
|
||||
return ::boost::yap::get(
|
||||
::boost::yap::deref(static_cast<Expr &&>(expr)), i);
|
||||
} else {
|
||||
if constexpr (std::is_lvalue_reference<Expr>::value) {
|
||||
return expr.elements[i];
|
||||
} else {
|
||||
return std::move(expr.elements[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Returns <code>get(expr, boost::hana::llong_c<I>)</code>. */
|
||||
template<long long I, typename Expr>
|
||||
constexpr decltype(auto) get_c(Expr && expr)
|
||||
{
|
||||
return ::boost::yap::get(static_cast<Expr &&>(expr), hana::llong_c<I>);
|
||||
}
|
||||
|
||||
/** Returns the left operand in a binary operator expression.
|
||||
|
||||
Equivalent to <code>get(expr, 0_c)</code>.
|
||||
|
||||
\note <code>left()</code> is only valid if \a Expr is a binary
|
||||
operator expression.
|
||||
*/
|
||||
template<typename Expr>
|
||||
constexpr decltype(auto) left(Expr && expr)
|
||||
{
|
||||
using namespace hana::literals;
|
||||
return ::boost::yap::get(static_cast<Expr &&>(expr), 0_c);
|
||||
constexpr expr_kind kind = detail::remove_cv_ref_t<Expr>::kind;
|
||||
static_assert(
|
||||
kind == expr_kind::expr_ref ||
|
||||
detail::arity_of<kind>() == detail::expr_arity::two,
|
||||
"left() is only defined for binary expressions.");
|
||||
}
|
||||
|
||||
/** Returns the right operand in a binary operator expression.
|
||||
|
||||
Equivalent to <code>get(expr, 1_c)</code>.
|
||||
|
||||
\note <code>right()</code> is only valid if \a Expr is a binary
|
||||
operator expression.
|
||||
*/
|
||||
template<typename Expr>
|
||||
constexpr decltype(auto) right(Expr && expr)
|
||||
{
|
||||
using namespace hana::literals;
|
||||
return ::boost::yap::get(static_cast<Expr &&>(expr), 1_c);
|
||||
constexpr expr_kind kind = detail::remove_cv_ref_t<Expr>::kind;
|
||||
static_assert(
|
||||
kind == expr_kind::expr_ref ||
|
||||
detail::arity_of<kind>() == detail::expr_arity::two,
|
||||
"right() is only defined for binary expressions.");
|
||||
}
|
||||
|
||||
/** Returns the condition expression in an if_else expression.
|
||||
|
||||
Equivalent to <code>get(expr, 0_c)</code>.
|
||||
|
||||
\note <code>cond()</code> is only valid if \a Expr is an
|
||||
<code>expr_kind::if_else</code> expression.
|
||||
*/
|
||||
template<typename Expr>
|
||||
constexpr decltype(auto) cond(Expr && expr)
|
||||
{
|
||||
using namespace hana::literals;
|
||||
return ::boost::yap::get(static_cast<Expr &&>(expr), 0_c);
|
||||
constexpr expr_kind kind = detail::remove_cv_ref_t<Expr>::kind;
|
||||
static_assert(
|
||||
kind == expr_kind::expr_ref || kind == expr_kind::if_else,
|
||||
"cond() is only defined for if_else expressions.");
|
||||
}
|
||||
|
||||
/** Returns the then-expression in an if_else expression.
|
||||
|
||||
Equivalent to <code>get(expr, 1_c)</code>.
|
||||
|
||||
\note <code>then()</code> is only valid if \a Expr is an
|
||||
<code>expr_kind::if_else</code> expression.
|
||||
*/
|
||||
template<typename Expr>
|
||||
constexpr decltype(auto) then(Expr && expr)
|
||||
{
|
||||
using namespace hana::literals;
|
||||
return ::boost::yap::get(static_cast<Expr &&>(expr), 1_c);
|
||||
constexpr expr_kind kind = detail::remove_cv_ref_t<Expr>::kind;
|
||||
static_assert(
|
||||
kind == expr_kind::expr_ref || kind == expr_kind::if_else,
|
||||
"then() is only defined for if_else expressions.");
|
||||
}
|
||||
|
||||
/** Returns the else-expression in an if_else expression.
|
||||
|
||||
Equivalent to <code>get(expr, 2_c)</code>.
|
||||
|
||||
\note <code>else_()</code> is only valid if \a Expr is an
|
||||
<code>expr_kind::if_else</code> expression.
|
||||
*/
|
||||
template<typename Expr>
|
||||
constexpr decltype(auto) else_(Expr && expr)
|
||||
{
|
||||
using namespace hana::literals;
|
||||
return ::boost::yap::get(static_cast<Expr &&>(expr), 2_c);
|
||||
constexpr expr_kind kind = detail::remove_cv_ref_t<Expr>::kind;
|
||||
static_assert(
|
||||
kind == expr_kind::expr_ref || kind == expr_kind::if_else,
|
||||
"else_() is only defined for if_else expressions.");
|
||||
}
|
||||
|
||||
/** Returns the callable in a call expression.
|
||||
|
||||
Equivalent to <code>get(expr, 0)</code>.
|
||||
|
||||
\note <code>callable()</code> is only valid if \a Expr is an
|
||||
<code>expr_kind::call</code> expression.
|
||||
*/
|
||||
template<typename Expr>
|
||||
constexpr decltype(auto) callable(Expr && expr)
|
||||
{
|
||||
return ::boost::yap::get(static_cast<Expr &&>(expr), hana::llong_c<0>);
|
||||
constexpr expr_kind kind = detail::remove_cv_ref_t<Expr>::kind;
|
||||
static_assert(
|
||||
kind == expr_kind::expr_ref ||
|
||||
detail::arity_of<kind>() == detail::expr_arity::n,
|
||||
"callable() is only defined for call expressions.");
|
||||
}
|
||||
|
||||
/** Returns the <i>i-th</i> argument expression in a call expression.
|
||||
|
||||
Equivalent to <code>get(expr, i + 1)</code>.
|
||||
|
||||
\note <code>argument()</code> is only valid if \a Expr is an
|
||||
<code>expr_kind::call</code> expression.
|
||||
*/
|
||||
template<long long I, typename Expr>
|
||||
constexpr decltype(auto) argument(Expr && expr, hana::llong<I> i)
|
||||
{
|
||||
return ::boost::yap::get(
|
||||
static_cast<Expr &&>(expr), hana::llong_c<I + 1>);
|
||||
constexpr expr_kind kind = detail::remove_cv_ref_t<Expr>::kind;
|
||||
static_assert(
|
||||
kind == expr_kind::expr_ref ||
|
||||
detail::arity_of<kind>() == detail::expr_arity::n,
|
||||
"argument() is only defined for call expressions.");
|
||||
static_assert(
|
||||
kind == expr_kind::expr_ref ||
|
||||
(0 <= I && I < decltype(hana::size(expr.elements))::value - 1),
|
||||
"I must be a valid call-expression argument index.");
|
||||
}
|
||||
|
||||
/** Makes a new expression instantiated from the expression template \a
|
||||
ExprTemplate, of kind \a Kind, with the given values as its
|
||||
elements.
|
||||
|
||||
For each parameter P:
|
||||
|
||||
- If P is an expression, P is moved into the result if P is an
|
||||
rvalue and captured by reference into the result otherwise.
|
||||
|
||||
- Otherwise, P is wrapped in a terminal expression.
|
||||
|
||||
\note <code>make_expression()</code> is only valid if the number of
|
||||
parameters passed is appropriate for \a Kind.
|
||||
*/
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind Kind,
|
||||
typename... T>
|
||||
constexpr auto make_expression(T &&... t)
|
||||
{
|
||||
constexpr detail::expr_arity arity = detail::arity_of<Kind>();
|
||||
static_assert(
|
||||
(arity == detail::expr_arity::one && sizeof...(T) == 1) ||
|
||||
(arity == detail::expr_arity::two && sizeof...(T) == 2) ||
|
||||
(arity == detail::expr_arity::three && sizeof...(T) == 3) ||
|
||||
arity == detail::expr_arity::n,
|
||||
"The number of parameters passed to make_expression() must "
|
||||
"match the arity "
|
||||
"implied by the expr_kind template parameter.");
|
||||
using tuple_type =
|
||||
hana::tuple<detail::operand_type_t<ExprTemplate, T>...>;
|
||||
return ExprTemplate<Kind, tuple_type>{tuple_type{
|
||||
detail::make_operand<detail::operand_type_t<ExprTemplate, T>>{}(
|
||||
static_cast<T &&>(t))...}};
|
||||
}
|
||||
|
||||
/** Makes a new terminal expression instantiated from the expression
|
||||
template \a ExprTemplate, with the given value as its sole element.
|
||||
|
||||
\note <code>make_terminal()</code> is only valid if \a T is \b not
|
||||
an expression.
|
||||
*/
|
||||
template<template<expr_kind, class> class ExprTemplate, typename T>
|
||||
constexpr auto make_terminal(T && t)
|
||||
{
|
||||
static_assert(
|
||||
!is_expr<T>::value,
|
||||
"make_terminal() is only defined for non expressions.");
|
||||
using result_type = detail::operand_type_t<ExprTemplate, T>;
|
||||
using tuple_type = decltype(std::declval<result_type>().elements);
|
||||
return result_type{tuple_type{static_cast<T &&>(t)}};
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_CONSTEXPR_IF
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
bool IsExpr>
|
||||
struct as_expr_impl
|
||||
{
|
||||
constexpr decltype(auto) operator()(T && t)
|
||||
{
|
||||
return static_cast<T &&>(t);
|
||||
}
|
||||
};
|
||||
|
||||
template<template<expr_kind, class> class ExprTemplate, typename T>
|
||||
struct as_expr_impl<ExprTemplate, T, false>
|
||||
{
|
||||
constexpr decltype(auto) operator()(T && t)
|
||||
{
|
||||
return make_terminal<ExprTemplate>(static_cast<T &&>(t));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** Returns an expression formed from \a t as follows:
|
||||
|
||||
- If \a t is an expression, \a t is forwarded to the caller.
|
||||
|
||||
- Otherwise, \a t is wrapped in a terminal expression.
|
||||
*/
|
||||
template<template<expr_kind, class> class ExprTemplate, typename T>
|
||||
constexpr decltype(auto) as_expr(T && t)
|
||||
{
|
||||
#ifdef BOOST_NO_CONSTEXPR_IF
|
||||
return detail::as_expr_impl<ExprTemplate, T, is_expr<T>::value>{}(
|
||||
static_cast<T &&>(t));
|
||||
#else
|
||||
if constexpr (is_expr<T>::value) {
|
||||
return static_cast<T &&>(t);
|
||||
} else {
|
||||
return make_terminal<ExprTemplate>(static_cast<T &&>(t));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** A callable type that evaluates its contained expression when called.
|
||||
|
||||
\see <code>make_expression_function()</code>
|
||||
*/
|
||||
template<typename Expr>
|
||||
struct expression_function
|
||||
{
|
||||
template<typename... U>
|
||||
constexpr decltype(auto) operator()(U &&... u)
|
||||
{
|
||||
return ::boost::yap::evaluate(expr, static_cast<U &&>(u)...);
|
||||
}
|
||||
|
||||
Expr expr;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<expr_kind Kind, typename Tuple>
|
||||
struct expression_function_expr
|
||||
{
|
||||
static const expr_kind kind = Kind;
|
||||
Tuple elements;
|
||||
};
|
||||
}
|
||||
|
||||
/** Returns a callable object that \a expr has been forwarded into. This
|
||||
is useful for using expressions as function objects.
|
||||
|
||||
Lvalue expressions are stored in the result by reference; rvalue
|
||||
expressions are moved into the result.
|
||||
|
||||
\note <code>make_expression_function()</code> is only valid if \a
|
||||
Expr is an expression.
|
||||
*/
|
||||
template<typename Expr>
|
||||
constexpr auto make_expression_function(Expr && expr)
|
||||
{
|
||||
static_assert(
|
||||
is_expr<Expr>::value,
|
||||
"make_expression_function() is only defined for expressions.");
|
||||
using stored_type =
|
||||
detail::operand_type_t<detail::expression_function_expr, Expr &&>;
|
||||
return expression_function<stored_type>{
|
||||
detail::make_operand<stored_type>{}(static_cast<Expr &&>(expr))};
|
||||
}
|
||||
}}
|
||||
|
||||
#include <boost/yap/detail/transform.hpp>
|
||||
|
||||
namespace boost { namespace yap {
|
||||
|
||||
/** Returns a transform object that replaces placeholders within an
|
||||
expression with the given values.
|
||||
*/
|
||||
template<typename... T>
|
||||
constexpr auto replacements(T &&... t)
|
||||
{
|
||||
return detail::placeholder_transform_t<T...>(static_cast<T &&>(t)...);
|
||||
}
|
||||
|
||||
/** Returns \a expr with the placeholders replaced by YAP terminals
|
||||
containing the given values.
|
||||
|
||||
\note <code>replace_placeholders(expr, t...)</code> is only valid if
|
||||
\a expr is an expression, and <code>max_p <= sizeof...(t)</code>,
|
||||
where <code>max_p</code> is the maximum placeholder index in \a expr.
|
||||
*/
|
||||
template<typename Expr, typename... T>
|
||||
constexpr decltype(auto) replace_placeholders(Expr && expr, T &&... t)
|
||||
{
|
||||
static_assert(
|
||||
is_expr<Expr>::value,
|
||||
"evaluate() is only defined for expressions.");
|
||||
return transform(
|
||||
static_cast<Expr &&>(expr), replacements(static_cast<T &&>(t)...));
|
||||
}
|
||||
|
||||
/** Returns a transform object that evaluates an expression using the
|
||||
built-in semantics. The transform replaces any placeholders with the
|
||||
given values.
|
||||
*/
|
||||
template<typename... T>
|
||||
constexpr auto evaluation(T &&... t)
|
||||
{
|
||||
return detail::evaluation_transform_t<T...>(static_cast<T &&>(t)...);
|
||||
}
|
||||
|
||||
/** Evaluates \a expr using the built-in semantics, replacing any
|
||||
placeholders with the given values.
|
||||
|
||||
\note <code>evaluate(expr)</code> is only valid if \a expr is an
|
||||
expression.
|
||||
*/
|
||||
template<typename Expr, typename... T>
|
||||
constexpr decltype(auto) evaluate(Expr && expr, T &&... t)
|
||||
{
|
||||
static_assert(
|
||||
is_expr<Expr>::value,
|
||||
"evaluate() is only defined for expressions.");
|
||||
return transform(
|
||||
static_cast<Expr &&>(expr), evaluation(static_cast<T &&>(t)...));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename... Transforms>
|
||||
constexpr auto make_transform_tuple(Transforms &... transforms)
|
||||
{
|
||||
return hana::tuple<Transforms *...>{&transforms...};
|
||||
}
|
||||
|
||||
template<bool Strict>
|
||||
struct transform_
|
||||
{
|
||||
template<typename Expr, typename Transform, typename... Transforms>
|
||||
constexpr decltype(auto) operator()(
|
||||
Expr && expr, Transform & transform, Transforms &... transforms) const
|
||||
{
|
||||
auto transform_tuple =
|
||||
detail::make_transform_tuple(transform, transforms...);
|
||||
constexpr expr_kind kind = detail::remove_cv_ref_t<Expr>::kind;
|
||||
return detail::
|
||||
transform_impl<Strict, 0, kind == expr_kind::expr_ref>{}(
|
||||
static_cast<Expr &&>(expr), transform_tuple);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Returns the result of transforming (all or part of) \a expr using
|
||||
whatever overloads of <code>Transform::operator()</code> match \a
|
||||
expr.
|
||||
|
||||
\note Transformations can do anything: they may have side effects;
|
||||
they may mutate values; they may mutate types; and they may do any
|
||||
combination of these.
|
||||
*/
|
||||
template<typename Expr, typename Transform, typename... Transforms>
|
||||
constexpr decltype(auto)
|
||||
transform(Expr && expr, Transform && transform, Transforms &&... transforms)
|
||||
{
|
||||
static_assert(
|
||||
is_expr<Expr>::value,
|
||||
"transform() is only defined for expressions.");
|
||||
return detail::transform_<false>{}(
|
||||
static_cast<Expr &&>(expr), transform, transforms...);
|
||||
}
|
||||
|
||||
/** Returns the result of transforming \a expr using whichever overload of
|
||||
<code>Transform::operator()</code> best matches \a expr. If no
|
||||
overload of <code>Transform::operator()</code> matches, a compile-time
|
||||
error results.
|
||||
|
||||
\note Transformations can do anything: they may have side effects;
|
||||
they may mutate values; they may mutate types; and they may do any
|
||||
combination of these.
|
||||
*/
|
||||
template<typename Expr, typename Transform, typename... Transforms>
|
||||
constexpr decltype(auto) transform_strict(
|
||||
Expr && expr, Transform && transform, Transforms &&... transforms)
|
||||
{
|
||||
static_assert(
|
||||
is_expr<Expr>::value,
|
||||
"transform() is only defined for expressions.");
|
||||
return detail::transform_<true>{}(
|
||||
static_cast<Expr &&>(expr), transform, transforms...);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
214
install/boost_1_75_0/include/boost/yap/algorithm_fwd.hpp
Normal file
214
install/boost_1_75_0/include/boost/yap/algorithm_fwd.hpp
Normal file
@@ -0,0 +1,214 @@
|
||||
// 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_ALGORITHM_FWD_HPP_INCLUDED
|
||||
#define BOOST_YAP_ALGORITHM_FWD_HPP_INCLUDED
|
||||
|
||||
#include <boost/yap/config.hpp>
|
||||
|
||||
#include <boost/hana/integral_constant.hpp>
|
||||
#include <boost/hana/tuple.hpp>
|
||||
#include <boost/hana/core/is_a.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace yap {
|
||||
|
||||
/** The enumeration representing all the kinds of expressions supported in
|
||||
YAP.
|
||||
*/
|
||||
enum class expr_kind {
|
||||
expr_ref =
|
||||
0, ///< A (possibly \c const) reference to another expression.
|
||||
|
||||
terminal = 1, ///< A terminal expression.
|
||||
|
||||
// unary
|
||||
unary_plus = 2, ///< \c +
|
||||
negate = 3, ///< \c -
|
||||
dereference = 4, ///< \c *
|
||||
complement = 5, ///< \c ~
|
||||
address_of = 6, ///< \c &
|
||||
logical_not = 7, ///< \c !
|
||||
pre_inc = 8, ///< \c ++
|
||||
pre_dec = 9, ///< \c \-\-
|
||||
post_inc = 10, ///< \c ++(int)
|
||||
post_dec = 11, ///< \c \-\-(int)
|
||||
|
||||
// binary
|
||||
shift_left = 12, ///< \c <<
|
||||
shift_right = 13, ///< \c >>
|
||||
multiplies = 14, ///< \c *
|
||||
divides = 15, ///< \c /
|
||||
modulus = 16, ///< \c %
|
||||
plus = 17, ///< \c +
|
||||
minus = 18, ///< \c -
|
||||
less = 19, ///< \c <
|
||||
greater = 20, ///< \c >
|
||||
less_equal = 21, ///< \c <=
|
||||
greater_equal = 22, ///< \c >=
|
||||
equal_to = 23, ///< \c ==
|
||||
not_equal_to = 24, ///< \c !=
|
||||
logical_or = 25, ///< \c ||
|
||||
logical_and = 26, ///< \c &&
|
||||
bitwise_and = 27, ///< \c &
|
||||
bitwise_or = 28, ///< \c |
|
||||
bitwise_xor = 29, ///< \c ^
|
||||
comma = 30, ///< \c ,
|
||||
mem_ptr = 31, ///< \c ->*
|
||||
assign = 32, ///< \c =
|
||||
shift_left_assign = 33, ///< \c <<=
|
||||
shift_right_assign = 34, ///< \c >>=
|
||||
multiplies_assign = 35, ///< \c *=
|
||||
divides_assign = 36, ///< \c /=
|
||||
modulus_assign = 37, ///< \c %=
|
||||
plus_assign = 38, ///< \c +=
|
||||
minus_assign = 39, ///< \c -=
|
||||
bitwise_and_assign = 40, ///< \c &=
|
||||
bitwise_or_assign = 41, ///< \c |=
|
||||
bitwise_xor_assign = 42, ///< \c ^=
|
||||
subscript = 43, ///< \c []
|
||||
|
||||
// ternary
|
||||
if_else = 44, ///< Analogous to \c ?: .
|
||||
|
||||
// n-ary
|
||||
call = 45 ///< \c ()
|
||||
};
|
||||
|
||||
/** The type used to represent the index of a placeholder terminal. */
|
||||
template<long long I>
|
||||
struct placeholder : hana::llong<I>
|
||||
{
|
||||
};
|
||||
|
||||
#ifdef BOOST_YAP_DOXYGEN
|
||||
|
||||
/** A metafunction that evaluates to std::true_type if \a Expr is an
|
||||
Expression, and std::false_type otherwise. */
|
||||
template<typename Expr>
|
||||
struct is_expr;
|
||||
|
||||
#else
|
||||
|
||||
template<expr_kind Kind, typename Tuple>
|
||||
struct expression;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// void_t
|
||||
|
||||
template<class...>
|
||||
using void_t = void;
|
||||
|
||||
// remove_cv_ref
|
||||
|
||||
template<typename T>
|
||||
struct remove_cv_ref : std::remove_cv<std::remove_reference_t<T>>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using remove_cv_ref_t = typename remove_cv_ref<T>::type;
|
||||
}
|
||||
|
||||
template<
|
||||
typename Expr,
|
||||
typename = detail::void_t<>,
|
||||
typename = detail::void_t<>>
|
||||
struct is_expr : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Expr>
|
||||
struct is_expr<
|
||||
Expr,
|
||||
detail::void_t<decltype(detail::remove_cv_ref_t<Expr>::kind)>,
|
||||
detail::void_t<decltype(std::declval<Expr>().elements)>>
|
||||
: std::integral_constant<
|
||||
bool,
|
||||
std::is_same<
|
||||
std::remove_cv_t<decltype(
|
||||
detail::remove_cv_ref_t<Expr>::kind)>,
|
||||
expr_kind>::value &&
|
||||
hana::is_a<
|
||||
hana::tuple_tag,
|
||||
decltype(std::declval<Expr>().elements)>>
|
||||
{
|
||||
};
|
||||
|
||||
#endif // BOOST_YAP_DOXYGEN
|
||||
|
||||
/** A convenience alias for a terminal expression holding a \a T,
|
||||
instantiated from expression template \a expr_template. */
|
||||
template<template<expr_kind, class> class expr_template, typename T>
|
||||
using terminal = expr_template<expr_kind::terminal, hana::tuple<T>>;
|
||||
|
||||
/** A convenience alias for a reference expression holding an expression
|
||||
\a T, instantiated from expression template \a expr_template. */
|
||||
template<template<expr_kind, class> class expr_template, typename T>
|
||||
using expression_ref = expr_template<
|
||||
expr_kind::expr_ref,
|
||||
hana::tuple<std::remove_reference_t<T> *>>;
|
||||
|
||||
#ifndef BOOST_YAP_DOXYGEN
|
||||
|
||||
template<typename Expr, typename... T>
|
||||
constexpr decltype(auto) evaluate(Expr && expr, T &&... t);
|
||||
|
||||
template<typename Expr, typename Transform, typename... Transforms>
|
||||
constexpr decltype(auto) transform(
|
||||
Expr && expr, Transform && transform, Transforms &&... transforms);
|
||||
|
||||
template<typename Expr, typename Transform, typename... Transforms>
|
||||
constexpr decltype(auto) transform_strict(
|
||||
Expr && expr, Transform && transform, Transforms &&... transforms);
|
||||
|
||||
template<typename T>
|
||||
constexpr decltype(auto) deref(T && x);
|
||||
|
||||
template<typename Expr>
|
||||
constexpr decltype(auto) value(Expr && expr);
|
||||
|
||||
#endif // BOOST_YAP_DOXYGEN
|
||||
|
||||
namespace literals {
|
||||
|
||||
/** Creates literal placeholders. Placeholder indices are 1-based. */
|
||||
template<char... c>
|
||||
constexpr auto operator"" _p()
|
||||
{
|
||||
using i = hana::llong<hana::ic_detail::parse<sizeof...(c)>({c...})>;
|
||||
static_assert(1 <= i::value, "Placeholders must be >= 1.");
|
||||
return expression<
|
||||
expr_kind::terminal,
|
||||
hana::tuple<placeholder<i::value>>>{};
|
||||
}
|
||||
}
|
||||
|
||||
/** Used as the tag-type passed to a transform function written in the
|
||||
tag-transform form. */
|
||||
template<expr_kind Kind>
|
||||
struct expr_tag
|
||||
{
|
||||
static const expr_kind kind = Kind;
|
||||
};
|
||||
|
||||
/** Used as the expression template returned by some operations inside YAP
|
||||
when YAP does not have an expression template it was told to use. For
|
||||
instance, if transform() creates a new expression by transforming an
|
||||
existing expression's elements, it will attempt to create the new
|
||||
expression using the existing one's expression template. If no such
|
||||
template exists because the existing expression was not made from an
|
||||
expression template, minimal_expr is used. */
|
||||
template<expr_kind Kind, typename Tuple>
|
||||
struct minimal_expr
|
||||
{
|
||||
static expr_kind const kind = Kind;
|
||||
Tuple elements;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
21
install/boost_1_75_0/include/boost/yap/config.hpp
Normal file
21
install/boost_1_75_0/include/boost/yap/config.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// 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_CONFIG_HPP_INCLUDED
|
||||
#define BOOST_YAP_CONFIG_HPP_INCLUDED
|
||||
|
||||
|
||||
#ifndef BOOST_NO_CONSTEXPR_IF
|
||||
/** Indicates whether the compiler supports constexpr if.
|
||||
|
||||
If the user does not define any value for this, we assume that the
|
||||
compiler does not have the necessary support. Note that this is a
|
||||
temporary hack; this should eventually be a Boost-wide macro. */
|
||||
#define BOOST_NO_CONSTEXPR_IF
|
||||
#elif BOOST_NO_CONSTEXPR_IF == 0
|
||||
#undef BOOST_NO_CONSTEXPR_IF
|
||||
#endif
|
||||
|
||||
#endif
|
||||
598
install/boost_1_75_0/include/boost/yap/detail/algorithm.hpp
Normal file
598
install/boost_1_75_0/include/boost/yap/detail/algorithm.hpp
Normal file
@@ -0,0 +1,598 @@
|
||||
// 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_EXPRESSION_HPP_INCLUDED
|
||||
#define BOOST_YAP_DETAIL_EXPRESSION_HPP_INCLUDED
|
||||
|
||||
#include <boost/yap/algorithm_fwd.hpp>
|
||||
|
||||
#include <boost/hana/size.hpp>
|
||||
#include <boost/hana/tuple.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace boost { namespace yap { namespace detail {
|
||||
|
||||
// static_const
|
||||
|
||||
template<typename T>
|
||||
struct static_const
|
||||
{
|
||||
static constexpr T value{};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr T static_const<T>::value;
|
||||
|
||||
|
||||
// partial_decay
|
||||
|
||||
template<typename T>
|
||||
struct partial_decay
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct partial_decay<T[]>
|
||||
{
|
||||
using type = T *;
|
||||
};
|
||||
template<typename T, std::size_t N>
|
||||
struct partial_decay<T[N]>
|
||||
{
|
||||
using type = T *;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct partial_decay<T (&)[]>
|
||||
{
|
||||
using type = T *;
|
||||
};
|
||||
template<typename T, std::size_t N>
|
||||
struct partial_decay<T (&)[N]>
|
||||
{
|
||||
using type = T *;
|
||||
};
|
||||
|
||||
template<typename R, typename... A>
|
||||
struct partial_decay<R(A...)>
|
||||
{
|
||||
using type = R (*)(A...);
|
||||
};
|
||||
template<typename R, typename... A>
|
||||
struct partial_decay<R(A..., ...)>
|
||||
{
|
||||
using type = R (*)(A..., ...);
|
||||
};
|
||||
|
||||
template<typename R, typename... A>
|
||||
struct partial_decay<R (&)(A...)>
|
||||
{
|
||||
using type = R (*)(A...);
|
||||
};
|
||||
template<typename R, typename... A>
|
||||
struct partial_decay<R (&)(A..., ...)>
|
||||
{
|
||||
using type = R (*)(A..., ...);
|
||||
};
|
||||
|
||||
template<typename R, typename... A>
|
||||
struct partial_decay<R (*&)(A...)>
|
||||
{
|
||||
using type = R (*)(A...);
|
||||
};
|
||||
template<typename R, typename... A>
|
||||
struct partial_decay<R (*&)(A..., ...)>
|
||||
{
|
||||
using type = R (*)(A..., ...);
|
||||
};
|
||||
|
||||
|
||||
// operand_value_type_phase_1
|
||||
|
||||
template<
|
||||
typename T,
|
||||
typename U = typename detail::partial_decay<T>::type,
|
||||
bool AddRValueRef = std::is_same<T, U>::value && !std::is_const<U>::value>
|
||||
struct operand_value_type_phase_1;
|
||||
|
||||
template<typename T, typename U>
|
||||
struct operand_value_type_phase_1<T, U, true>
|
||||
{
|
||||
using type = U &&;
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct operand_value_type_phase_1<T, U, false>
|
||||
{
|
||||
using type = U;
|
||||
};
|
||||
|
||||
|
||||
// expr_ref
|
||||
|
||||
template<template<expr_kind, class> class ExprTemplate, typename T>
|
||||
struct expr_ref
|
||||
{
|
||||
using type = expression_ref<ExprTemplate, T>;
|
||||
};
|
||||
|
||||
template<template<expr_kind, class> class ExprTemplate, typename Tuple>
|
||||
struct expr_ref<ExprTemplate, ExprTemplate<expr_kind::expr_ref, Tuple> &>
|
||||
{
|
||||
using type = ExprTemplate<expr_kind::expr_ref, Tuple>;
|
||||
};
|
||||
|
||||
template<template<expr_kind, class> class ExprTemplate, typename Tuple>
|
||||
struct expr_ref<
|
||||
ExprTemplate,
|
||||
ExprTemplate<expr_kind::expr_ref, Tuple> const &>
|
||||
{
|
||||
using type = ExprTemplate<expr_kind::expr_ref, Tuple>;
|
||||
};
|
||||
|
||||
template<template<expr_kind, class> class ExprTemplate, typename T>
|
||||
using expr_ref_t = typename expr_ref<ExprTemplate, T>::type;
|
||||
|
||||
template<template<expr_kind, class> class ExprTemplate, typename T>
|
||||
struct expr_ref_tuple;
|
||||
|
||||
template<template<expr_kind, class> class ExprTemplate, typename Tuple>
|
||||
struct expr_ref_tuple<
|
||||
ExprTemplate,
|
||||
ExprTemplate<expr_kind::expr_ref, Tuple>>
|
||||
{
|
||||
using type = Tuple;
|
||||
};
|
||||
|
||||
template<template<expr_kind, class> class ExprTemplate, typename T>
|
||||
using expr_ref_tuple_t = typename expr_ref_tuple<ExprTemplate, T>::type;
|
||||
|
||||
|
||||
// operand_type
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U = typename operand_value_type_phase_1<T>::type,
|
||||
bool RemoveRefs = std::is_rvalue_reference<U>::value,
|
||||
bool IsExpr = is_expr<T>::value,
|
||||
bool IsLRef = std::is_lvalue_reference<T>::value>
|
||||
struct operand_type;
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
bool RemoveRefs>
|
||||
struct operand_type<ExprTemplate, T, U, RemoveRefs, true, false>
|
||||
{
|
||||
using type = remove_cv_ref_t<T>;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
bool RemoveRefs>
|
||||
struct operand_type<ExprTemplate, T, U, RemoveRefs, true, true>
|
||||
{
|
||||
using type = expr_ref_t<ExprTemplate, T>;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
bool RemoveRefs,
|
||||
bool IsLRef>
|
||||
struct operand_type<ExprTemplate, T, U, RemoveRefs, true, IsLRef>
|
||||
{
|
||||
using type = remove_cv_ref_t<T>;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
bool IsLRef>
|
||||
struct operand_type<ExprTemplate, T, U, true, false, IsLRef>
|
||||
{
|
||||
using type = terminal<ExprTemplate, std::remove_reference_t<U>>;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
bool IsLRef>
|
||||
struct operand_type<ExprTemplate, T, U, false, false, IsLRef>
|
||||
{
|
||||
using type = terminal<ExprTemplate, U>;
|
||||
};
|
||||
|
||||
template<template<expr_kind, class> class ExprTemplate, typename T>
|
||||
using operand_type_t = typename operand_type<ExprTemplate, T>::type;
|
||||
|
||||
|
||||
// make_operand
|
||||
|
||||
template<typename T>
|
||||
struct make_operand
|
||||
{
|
||||
template<typename U>
|
||||
constexpr auto operator()(U && u)
|
||||
{
|
||||
return T{static_cast<U &&>(u)};
|
||||
}
|
||||
};
|
||||
|
||||
template<template<expr_kind, class> class ExprTemplate, typename Tuple>
|
||||
struct make_operand<ExprTemplate<expr_kind::expr_ref, Tuple>>
|
||||
{
|
||||
constexpr auto operator()(ExprTemplate<expr_kind::expr_ref, Tuple> expr)
|
||||
{
|
||||
return expr;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr auto operator()(U && u)
|
||||
{
|
||||
return ExprTemplate<expr_kind::expr_ref, Tuple>{
|
||||
Tuple{std::addressof(u)}};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// free_binary_op_result
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
typename U,
|
||||
bool TNonExprUExpr = !is_expr<T>::value && is_expr<U>::value,
|
||||
bool ULvalueRef = std::is_lvalue_reference<U>::value>
|
||||
struct free_binary_op_result;
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
typename U>
|
||||
struct free_binary_op_result<ExprTemplate, OpKind, T, U, true, true>
|
||||
{
|
||||
using lhs_type = operand_type_t<ExprTemplate, T>;
|
||||
using rhs_type = expr_ref_t<ExprTemplate, U>;
|
||||
using rhs_tuple_type = expr_ref_tuple_t<ExprTemplate, rhs_type>;
|
||||
using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
typename U>
|
||||
struct free_binary_op_result<ExprTemplate, OpKind, T, U, true, false>
|
||||
{
|
||||
using lhs_type = operand_type_t<ExprTemplate, T>;
|
||||
using rhs_type = remove_cv_ref_t<U>;
|
||||
using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
typename U>
|
||||
using free_binary_op_result_t =
|
||||
typename free_binary_op_result<ExprTemplate, OpKind, T, U>::type;
|
||||
|
||||
|
||||
// ternary_op_result
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V,
|
||||
bool Valid =
|
||||
is_expr<T>::value || is_expr<U>::value || is_expr<V>::value>
|
||||
struct ternary_op_result;
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V>
|
||||
struct ternary_op_result<ExprTemplate, T, U, V, true>
|
||||
{
|
||||
using cond_type = operand_type_t<ExprTemplate, T>;
|
||||
using then_type = operand_type_t<ExprTemplate, U>;
|
||||
using else_type = operand_type_t<ExprTemplate, V>;
|
||||
using type = ExprTemplate<
|
||||
expr_kind::if_else,
|
||||
hana::tuple<cond_type, then_type, else_type>>;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V>
|
||||
using ternary_op_result_t =
|
||||
typename ternary_op_result<ExprTemplate, T, U, V>::type;
|
||||
|
||||
|
||||
// udt_any_ternary_op_result
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V,
|
||||
template<class> class UdtTrait,
|
||||
bool Valid = !is_expr<T>::value && !is_expr<U>::value &&
|
||||
!is_expr<V>::value &&
|
||||
(UdtTrait<remove_cv_ref_t<T>>::value ||
|
||||
UdtTrait<remove_cv_ref_t<U>>::value ||
|
||||
UdtTrait<remove_cv_ref_t<V>>::value)>
|
||||
struct udt_any_ternary_op_result;
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V,
|
||||
template<class> class UdtTrait>
|
||||
struct udt_any_ternary_op_result<ExprTemplate, T, U, V, UdtTrait, true>
|
||||
{
|
||||
using cond_type = operand_type_t<ExprTemplate, T>;
|
||||
using then_type = operand_type_t<ExprTemplate, U>;
|
||||
using else_type = operand_type_t<ExprTemplate, V>;
|
||||
using type = ExprTemplate<
|
||||
expr_kind::if_else,
|
||||
hana::tuple<cond_type, then_type, else_type>>;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V,
|
||||
template<class> class UdtTrait>
|
||||
using udt_any_ternary_op_result_t =
|
||||
typename udt_any_ternary_op_result<ExprTemplate, T, U, V, UdtTrait>::
|
||||
type;
|
||||
|
||||
|
||||
// udt_unary_op_result
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
template<class> class UdtTrait,
|
||||
bool Valid = !is_expr<T>::value && UdtTrait<remove_cv_ref_t<T>>::value>
|
||||
struct udt_unary_op_result;
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
template<class> class UdtTrait>
|
||||
struct udt_unary_op_result<ExprTemplate, OpKind, T, UdtTrait, true>
|
||||
{
|
||||
using x_type = operand_type_t<ExprTemplate, T>;
|
||||
using type = ExprTemplate<OpKind, hana::tuple<x_type>>;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
template<class> class UdtTrait>
|
||||
using udt_unary_op_result_t =
|
||||
typename udt_unary_op_result<ExprTemplate, OpKind, T, UdtTrait>::type;
|
||||
|
||||
|
||||
// udt_udt_binary_op_result
|
||||
|
||||
template<typename T, template<class> class UdtTrait>
|
||||
struct is_udt_arg
|
||||
{
|
||||
static bool const value =
|
||||
!is_expr<T>::value && UdtTrait<remove_cv_ref_t<T>>::value;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
typename U,
|
||||
template<class> class TUdtTrait,
|
||||
template<class> class UUdtTrait,
|
||||
bool Valid =
|
||||
is_udt_arg<T, TUdtTrait>::value && is_udt_arg<U, UUdtTrait>::value>
|
||||
struct udt_udt_binary_op_result;
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
typename U,
|
||||
template<class> class TUdtTrait,
|
||||
template<class> class UUdtTrait>
|
||||
struct udt_udt_binary_op_result<
|
||||
ExprTemplate,
|
||||
OpKind,
|
||||
T,
|
||||
U,
|
||||
TUdtTrait,
|
||||
UUdtTrait,
|
||||
true>
|
||||
{
|
||||
using lhs_type = operand_type_t<ExprTemplate, T>;
|
||||
using rhs_type = operand_type_t<ExprTemplate, U>;
|
||||
using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
typename U,
|
||||
template<class> class TUdtTrait,
|
||||
template<class> class UUdtTrait>
|
||||
using udt_udt_binary_op_result_t = typename udt_udt_binary_op_result<
|
||||
ExprTemplate,
|
||||
OpKind,
|
||||
T,
|
||||
U,
|
||||
TUdtTrait,
|
||||
UUdtTrait>::type;
|
||||
|
||||
|
||||
// udt_any_binary_op_result
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
typename U,
|
||||
template<class> class UdtTrait,
|
||||
bool Valid = !is_expr<T>::value && !is_expr<U>::value &&
|
||||
(UdtTrait<remove_cv_ref_t<T>>::value ||
|
||||
UdtTrait<remove_cv_ref_t<U>>::value)>
|
||||
struct udt_any_binary_op_result;
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
typename U,
|
||||
template<class> class UdtTrait>
|
||||
struct udt_any_binary_op_result<ExprTemplate, OpKind, T, U, UdtTrait, true>
|
||||
{
|
||||
using lhs_type = operand_type_t<ExprTemplate, T>;
|
||||
using rhs_type = operand_type_t<ExprTemplate, U>;
|
||||
using type = ExprTemplate<OpKind, hana::tuple<lhs_type, rhs_type>>;
|
||||
};
|
||||
|
||||
template<
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
expr_kind OpKind,
|
||||
typename T,
|
||||
typename U,
|
||||
template<class> class UdtTrait>
|
||||
using udt_any_binary_op_result_t = typename udt_any_binary_op_result<
|
||||
ExprTemplate,
|
||||
OpKind,
|
||||
T,
|
||||
U,
|
||||
UdtTrait>::type;
|
||||
|
||||
|
||||
// not_copy_or_move
|
||||
|
||||
template<typename LeftT, typename RightT>
|
||||
struct copy_or_move : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct copy_or_move<T, T const &> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct copy_or_move<T, T &> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct copy_or_move<T, T &&> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
// expr_arity
|
||||
|
||||
enum class expr_arity { invalid, one, two, three, n };
|
||||
|
||||
template<expr_kind Kind>
|
||||
constexpr expr_arity arity_of()
|
||||
{
|
||||
switch (Kind) {
|
||||
case expr_kind::expr_ref:
|
||||
|
||||
case expr_kind::terminal:
|
||||
|
||||
// unary
|
||||
case expr_kind::unary_plus: // +
|
||||
case expr_kind::negate: // -
|
||||
case expr_kind::dereference: // *
|
||||
case expr_kind::complement: // ~
|
||||
case expr_kind::address_of: // &
|
||||
case expr_kind::logical_not: // !
|
||||
case expr_kind::pre_inc: // ++
|
||||
case expr_kind::pre_dec: // --
|
||||
case expr_kind::post_inc: // ++(int)
|
||||
case expr_kind::post_dec: // --(int)
|
||||
return expr_arity::one;
|
||||
|
||||
// binary
|
||||
case expr_kind::shift_left: // <<
|
||||
case expr_kind::shift_right: // >>
|
||||
case expr_kind::multiplies: // *
|
||||
case expr_kind::divides: // /
|
||||
case expr_kind::modulus: // %
|
||||
case expr_kind::plus: // +
|
||||
case expr_kind::minus: // -
|
||||
case expr_kind::less: // <
|
||||
case expr_kind::greater: // >
|
||||
case expr_kind::less_equal: // <=
|
||||
case expr_kind::greater_equal: // >=
|
||||
case expr_kind::equal_to: // ==
|
||||
case expr_kind::not_equal_to: // !=
|
||||
case expr_kind::logical_or: // ||
|
||||
case expr_kind::logical_and: // &&
|
||||
case expr_kind::bitwise_and: // &
|
||||
case expr_kind::bitwise_or: // |
|
||||
case expr_kind::bitwise_xor: // ^
|
||||
case expr_kind::comma: // :
|
||||
case expr_kind::mem_ptr: // ->*
|
||||
case expr_kind::assign: // =
|
||||
case expr_kind::shift_left_assign: // <<=
|
||||
case expr_kind::shift_right_assign: // >>=
|
||||
case expr_kind::multiplies_assign: // *=
|
||||
case expr_kind::divides_assign: // /=
|
||||
case expr_kind::modulus_assign: // %=
|
||||
case expr_kind::plus_assign: // +=
|
||||
case expr_kind::minus_assign: // -=
|
||||
case expr_kind::bitwise_and_assign: // &=
|
||||
case expr_kind::bitwise_or_assign: // |=
|
||||
case expr_kind::bitwise_xor_assign: // ^=
|
||||
case expr_kind::subscript: // []
|
||||
return expr_arity::two;
|
||||
|
||||
// ternary
|
||||
case expr_kind::if_else: // (analogous to) ?:
|
||||
return expr_arity::three;
|
||||
|
||||
// n-ary
|
||||
case expr_kind::call: // ()
|
||||
return expr_arity::n;
|
||||
|
||||
default: return expr_arity::invalid;
|
||||
}
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
591
install/boost_1_75_0/include/boost/yap/detail/transform.hpp
Normal file
591
install/boost_1_75_0/include/boost/yap/detail/transform.hpp
Normal file
@@ -0,0 +1,591 @@
|
||||
// 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 <boost/yap/algorithm_fwd.hpp>
|
||||
|
||||
#include <boost/hana/transform.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
|
||||
namespace boost { namespace yap { namespace detail {
|
||||
|
||||
template<int I, typename T, typename... Ts>
|
||||
struct nth_element_impl
|
||||
{
|
||||
using type = typename nth_element_impl<I - 1, Ts...>::type;
|
||||
};
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
struct nth_element_impl<0, T, Ts...>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<int I, typename... Ts>
|
||||
using nth_element = typename nth_element_impl<I, Ts...>::type;
|
||||
|
||||
template<typename T, bool RemoveRefs = std::is_rvalue_reference<T>::value>
|
||||
struct rvalue_ref_to_value;
|
||||
|
||||
template<typename T>
|
||||
struct rvalue_ref_to_value<T, true>
|
||||
{
|
||||
using type = typename std::remove_reference<T>::type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct rvalue_ref_to_value<T, false>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using rvalue_ref_to_value_t = typename rvalue_ref_to_value<T>::type;
|
||||
|
||||
template<bool IsRvalueRef>
|
||||
struct rvalue_mover
|
||||
{
|
||||
template<typename T>
|
||||
constexpr decltype(auto) operator()(T && t) const
|
||||
{
|
||||
return static_cast<T &&>(t);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct rvalue_mover<true>
|
||||
{
|
||||
template<typename T>
|
||||
constexpr std::remove_reference_t<T> operator()(T && t) const
|
||||
{
|
||||
return std::move(t);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... PlaceholderArgs>
|
||||
struct placeholder_transform_t
|
||||
{
|
||||
using tuple_t = hana::tuple<rvalue_ref_to_value_t<PlaceholderArgs>...>;
|
||||
|
||||
constexpr placeholder_transform_t(PlaceholderArgs &&... args) :
|
||||
placeholder_args_(static_cast<PlaceholderArgs &&>(args)...)
|
||||
{}
|
||||
|
||||
template<long long I>
|
||||
constexpr decltype(auto)
|
||||
operator()(expr_tag<expr_kind::terminal>, boost::yap::placeholder<I>) const
|
||||
{
|
||||
static_assert(
|
||||
I <= decltype(hana::size(std::declval<tuple_t>()))::value,
|
||||
"Out of range placeholder index,");
|
||||
using nth_type = nth_element<I - 1, PlaceholderArgs...>;
|
||||
return as_expr<minimal_expr>(
|
||||
rvalue_mover<!std::is_lvalue_reference<nth_type>::value>{}(
|
||||
placeholder_args_[hana::llong<I - 1>{}]));
|
||||
}
|
||||
|
||||
tuple_t placeholder_args_;
|
||||
};
|
||||
|
||||
template<typename... PlaceholderArgs>
|
||||
struct evaluation_transform_t
|
||||
{
|
||||
using tuple_t = hana::tuple<rvalue_ref_to_value_t<PlaceholderArgs>...>;
|
||||
|
||||
constexpr evaluation_transform_t(PlaceholderArgs &&... args) :
|
||||
placeholder_args_(static_cast<PlaceholderArgs &&>(args)...)
|
||||
{}
|
||||
|
||||
template<long long I>
|
||||
constexpr decltype(auto)
|
||||
operator()(expr_tag<expr_kind::terminal>, boost::yap::placeholder<I>) const
|
||||
{
|
||||
static_assert(
|
||||
I <= decltype(hana::size(std::declval<tuple_t>()))::value,
|
||||
"Out of range placeholder index,");
|
||||
using nth_type = nth_element<I - 1, PlaceholderArgs...>;
|
||||
return rvalue_mover<!std::is_lvalue_reference<nth_type>::value>{}(
|
||||
placeholder_args_[hana::llong<I - 1>{}]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr decltype(auto) operator()(expr_tag<expr_kind::terminal>, T && t) const
|
||||
{
|
||||
return static_cast<T &&>(t);
|
||||
}
|
||||
|
||||
#define BOOST_YAP_UNARY_OPERATOR_CASE(op, op_name) \
|
||||
template<typename T> \
|
||||
constexpr decltype(auto) operator()(expr_tag<expr_kind::op_name>, T && t) const \
|
||||
{ \
|
||||
return op transform( \
|
||||
as_expr<minimal_expr>(static_cast<T &&>(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<typename T>
|
||||
constexpr decltype(auto) operator()(expr_tag<expr_kind::post_inc>, T && t) const
|
||||
{
|
||||
return transform(
|
||||
as_expr<minimal_expr>(static_cast<T &&>(t)), *this)++;
|
||||
}
|
||||
template<typename T>
|
||||
constexpr decltype(auto) operator()(expr_tag<expr_kind::post_dec>, T && t) const
|
||||
{
|
||||
return transform(
|
||||
as_expr<minimal_expr>(static_cast<T &&>(t)), *this)--;
|
||||
}
|
||||
|
||||
#undef BOOST_YAP_UNARY_OPERATOR_CASE
|
||||
|
||||
#define BOOST_YAP_BINARY_OPERATOR_CASE(op, op_name) \
|
||||
template<typename T, typename U> \
|
||||
constexpr decltype(auto) operator()(expr_tag<expr_kind::op_name>, T && t, U && u) const \
|
||||
{ \
|
||||
return transform(as_expr<minimal_expr>(static_cast<T &&>(t)), *this) \
|
||||
op transform(as_expr<minimal_expr>(static_cast<U &&>(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<typename T, typename U>
|
||||
constexpr decltype(auto) operator()(expr_tag<expr_kind::comma>, T && t, U && u) const
|
||||
{
|
||||
return transform(
|
||||
as_expr<minimal_expr>(static_cast<T &&>(t)), *this),
|
||||
transform(
|
||||
as_expr<minimal_expr>(static_cast<U &&>(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<typename T, typename U>
|
||||
constexpr decltype(auto)
|
||||
operator()(expr_tag<expr_kind::subscript>, T && t, U && u) const
|
||||
{
|
||||
return transform(
|
||||
as_expr<minimal_expr>(static_cast<T &&>(t)), *this)[transform(
|
||||
as_expr<minimal_expr>(static_cast<U &&>(u)), *this)];
|
||||
}
|
||||
|
||||
#undef BOOST_YAP_BINARY_OPERATOR_CASE
|
||||
|
||||
template<typename T, typename U, typename V>
|
||||
constexpr decltype(auto)
|
||||
operator()(expr_tag<expr_kind::if_else>, T && t, U && u, V && v) const
|
||||
{
|
||||
return transform(as_expr<minimal_expr>(static_cast<T &&>(t)), *this)
|
||||
? transform(
|
||||
as_expr<minimal_expr>(static_cast<U &&>(u)), *this)
|
||||
: transform(
|
||||
as_expr<minimal_expr>(static_cast<V &&>(v)),
|
||||
*this);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
//[ evaluation_transform_call
|
||||
template<typename Callable, typename... Args>
|
||||
constexpr decltype(auto) operator()(
|
||||
expr_tag<expr_kind::call>, Callable && callable, Args &&... args) const
|
||||
{
|
||||
return transform(as_expr<minimal_expr>(static_cast<Callable &&>(callable)), *this)(
|
||||
transform(as_expr<minimal_expr>(static_cast<Args &&>(args)), *this)...
|
||||
);
|
||||
}
|
||||
//]
|
||||
// clang-format on
|
||||
|
||||
tuple_t placeholder_args_;
|
||||
};
|
||||
|
||||
|
||||
template<bool Strict, int I, bool IsExprRef>
|
||||
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<bool IsLvalueRef, bool IsTerminal, bool Strict>
|
||||
struct default_transform
|
||||
{
|
||||
template<typename Expr, typename TransformTuple>
|
||||
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
|
||||
{
|
||||
return static_cast<Expr &&>(expr);
|
||||
}
|
||||
};
|
||||
|
||||
template<bool IsLvalueRef, bool IsTerminal>
|
||||
struct default_transform<IsLvalueRef, IsTerminal, true>
|
||||
{
|
||||
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<typename Expr, typename TransformTuple>
|
||||
constexpr incomplete operator()(Expr && expr, TransformTuple transforms) const;
|
||||
};
|
||||
|
||||
template<
|
||||
expr_kind Kind,
|
||||
template<expr_kind, class> class ExprTemplate,
|
||||
typename OldTuple,
|
||||
typename NewTuple>
|
||||
constexpr auto make_expr_from_tuple(
|
||||
ExprTemplate<Kind, OldTuple> const & expr, NewTuple && tuple)
|
||||
{
|
||||
return ExprTemplate<Kind, NewTuple>{std::move(tuple)};
|
||||
}
|
||||
|
||||
template<expr_kind Kind, typename Expr, typename NewTuple>
|
||||
constexpr auto make_expr_from_tuple(Expr const & expr, NewTuple && tuple)
|
||||
{
|
||||
return minimal_expr<Kind, NewTuple>{std::move(tuple)};
|
||||
}
|
||||
|
||||
template<typename Expr, typename Tuple, typename TransformTuple>
|
||||
constexpr decltype(auto) transform_nonterminal(
|
||||
Expr const & expr, Tuple && tuple, TransformTuple transforms)
|
||||
{
|
||||
auto transformed_tuple =
|
||||
hana::transform(static_cast<Tuple &&>(tuple), [&](auto && element) {
|
||||
using element_t = decltype(element);
|
||||
auto const kind = remove_cv_ref_t<element_t>::kind;
|
||||
::boost::yap::detail::
|
||||
transform_impl<false, 0, kind == expr_kind::expr_ref>
|
||||
xform;
|
||||
return xform(static_cast<element_t &&>(element), transforms);
|
||||
});
|
||||
auto const kind = remove_cv_ref_t<Expr>::kind;
|
||||
return make_expr_from_tuple<kind>(expr, std::move(transformed_tuple));
|
||||
}
|
||||
|
||||
template<>
|
||||
struct default_transform<true, false, false>
|
||||
{
|
||||
template<typename Expr, typename TransformTuple>
|
||||
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
|
||||
{
|
||||
return transform_nonterminal(expr, expr.elements, transforms);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct default_transform<false, false, false>
|
||||
{
|
||||
template<typename Expr, typename TransformTuple>
|
||||
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<Expr>::kind;
|
||||
return detail::
|
||||
transform_impl<Strict, I + 1, kind == expr_kind::expr_ref>{}(
|
||||
static_cast<Expr &&>(expr), transforms);
|
||||
}
|
||||
};
|
||||
|
||||
template<bool Strict, typename Expr, typename TransformTuple, int I>
|
||||
struct next_or_default_transform<Strict, Expr, TransformTuple, I, false>
|
||||
{
|
||||
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<Expr>::kind;
|
||||
return default_transform<
|
||||
std::is_lvalue_reference<Expr>::value,
|
||||
kind == expr_kind::terminal,
|
||||
Strict>{}(static_cast<Expr &&>(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<TransformTuple>()))::value>{}(
|
||||
static_cast<Expr &&>(expr), transforms);
|
||||
}
|
||||
};
|
||||
|
||||
template<bool Strict, typename Expr, typename TransformTuple, int I>
|
||||
struct transform_expression_expr<
|
||||
Strict,
|
||||
Expr,
|
||||
TransformTuple,
|
||||
I,
|
||||
void_t<decltype((*std::declval<TransformTuple>()[hana::llong<I>{}])(
|
||||
std::declval<Expr>()))>>
|
||||
{
|
||||
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
|
||||
{
|
||||
return (*transforms[hana::llong<I>{}])(static_cast<Expr &&>(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<Strict, Expr, TransformTuple, I>{}(
|
||||
static_cast<Expr &&>(expr), transforms);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr decltype(auto) terminal_value(T && x)
|
||||
{
|
||||
return value_impl<true>(static_cast<T &&>(x));
|
||||
}
|
||||
|
||||
|
||||
template<bool Strict, typename Expr, typename TransformTuple, int I>
|
||||
struct transform_expression_tag<
|
||||
Strict,
|
||||
Expr,
|
||||
TransformTuple,
|
||||
I,
|
||||
expr_arity::one,
|
||||
void_t<decltype((*std::declval<TransformTuple>()[hana::llong<I>{}])(
|
||||
expr_tag<remove_cv_ref_t<Expr>::kind>{},
|
||||
terminal_value(::boost::yap::value(std::declval<Expr>()))))>>
|
||||
{
|
||||
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
|
||||
{
|
||||
return (*transforms[hana::llong<I>{}])(
|
||||
expr_tag<remove_cv_ref_t<Expr>::kind>{},
|
||||
terminal_value(
|
||||
::boost::yap::value(static_cast<Expr &&>(expr))));
|
||||
}
|
||||
};
|
||||
|
||||
template<bool Strict, typename Expr, typename TransformTuple, int I>
|
||||
struct transform_expression_tag<
|
||||
Strict,
|
||||
Expr,
|
||||
TransformTuple,
|
||||
I,
|
||||
expr_arity::two,
|
||||
void_t<decltype((*std::declval<TransformTuple>()[hana::llong<I>{}])(
|
||||
expr_tag<remove_cv_ref_t<Expr>::kind>{},
|
||||
terminal_value(::boost::yap::left(std::declval<Expr>())),
|
||||
terminal_value(::boost::yap::right(std::declval<Expr>()))))>>
|
||||
{
|
||||
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
|
||||
{
|
||||
return (*transforms[hana::llong<I>{}])(
|
||||
expr_tag<remove_cv_ref_t<Expr>::kind>{},
|
||||
terminal_value(::boost::yap::left(static_cast<Expr &&>(expr))),
|
||||
terminal_value(
|
||||
::boost::yap::right(static_cast<Expr &&>(expr))));
|
||||
}
|
||||
};
|
||||
|
||||
template<bool Strict, typename Expr, typename TransformTuple, int I>
|
||||
struct transform_expression_tag<
|
||||
Strict,
|
||||
Expr,
|
||||
TransformTuple,
|
||||
I,
|
||||
expr_arity::three,
|
||||
void_t<decltype((*std::declval<TransformTuple>()[hana::llong<I>{}])(
|
||||
expr_tag<remove_cv_ref_t<Expr>::kind>{},
|
||||
terminal_value(::boost::yap::cond(std::declval<Expr>())),
|
||||
terminal_value(::boost::yap::then(std::declval<Expr>())),
|
||||
terminal_value(::boost::yap::else_(std::declval<Expr>()))))>>
|
||||
{
|
||||
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
|
||||
{
|
||||
return (*transforms[hana::llong<I>{}])(
|
||||
expr_tag<remove_cv_ref_t<Expr>::kind>{},
|
||||
terminal_value(::boost::yap::cond(static_cast<Expr &&>(expr))),
|
||||
terminal_value(::boost::yap::then(static_cast<Expr &&>(expr))),
|
||||
terminal_value(
|
||||
::boost::yap::else_(static_cast<Expr &&>(expr))));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Expr, typename Transform>
|
||||
struct transform_call_unpacker
|
||||
{
|
||||
template<long long... I>
|
||||
constexpr auto operator()(
|
||||
Expr && expr,
|
||||
Transform & transform,
|
||||
std::integer_sequence<long long, I...>) const
|
||||
-> decltype(transform(
|
||||
expr_tag<expr_kind::call>{},
|
||||
terminal_value(::boost::yap::get(
|
||||
static_cast<Expr &&>(expr), hana::llong_c<I>))...))
|
||||
{
|
||||
return transform(
|
||||
expr_tag<expr_kind::call>{},
|
||||
terminal_value(::boost::yap::get(
|
||||
static_cast<Expr &&>(expr), hana::llong_c<I>))...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Expr>
|
||||
constexpr auto indices_for(Expr const & expr)
|
||||
{
|
||||
constexpr long long size = decltype(hana::size(expr.elements))::value;
|
||||
return std::make_integer_sequence<long long, size>();
|
||||
}
|
||||
|
||||
template<bool Strict, typename Expr, typename TransformTuple, int I>
|
||||
struct transform_expression_tag<
|
||||
Strict,
|
||||
Expr,
|
||||
TransformTuple,
|
||||
I,
|
||||
expr_arity::n,
|
||||
void_t<decltype(
|
||||
transform_call_unpacker<
|
||||
Expr,
|
||||
decltype(*std::declval<TransformTuple>()[hana::llong<I>{}])>{}(
|
||||
std::declval<Expr>(),
|
||||
*std::declval<TransformTuple>()[hana::llong<I>{}],
|
||||
indices_for(std::declval<Expr>())))>>
|
||||
{
|
||||
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
|
||||
{
|
||||
using transform_t = decltype(*transforms[hana::llong<I>{}]);
|
||||
return transform_call_unpacker<Expr, transform_t>{}(
|
||||
static_cast<Expr &&>(expr),
|
||||
*transforms[hana::llong<I>{}],
|
||||
indices_for(expr));
|
||||
}
|
||||
};
|
||||
|
||||
template<bool Strict, int I, bool IsExprRef>
|
||||
struct transform_impl
|
||||
{
|
||||
template<typename Expr, typename TransformTuple>
|
||||
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
|
||||
{
|
||||
constexpr expr_kind kind = detail::remove_cv_ref_t<Expr>::kind;
|
||||
return detail::transform_expression_tag<
|
||||
Strict,
|
||||
Expr,
|
||||
TransformTuple,
|
||||
I,
|
||||
detail::arity_of<kind>()>{}(
|
||||
static_cast<Expr &&>(expr), transforms);
|
||||
}
|
||||
};
|
||||
|
||||
template<bool Strict, int I>
|
||||
struct transform_impl<Strict, I, true>
|
||||
{
|
||||
template<typename Expr, typename TransformTuple>
|
||||
constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const
|
||||
{
|
||||
return detail::transform_impl<Strict, I, false>{}(
|
||||
::boost::yap::deref(static_cast<Expr &&>(expr)), transforms);
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
338
install/boost_1_75_0/include/boost/yap/expression.hpp
Normal file
338
install/boost_1_75_0/include/boost/yap/expression.hpp
Normal file
@@ -0,0 +1,338 @@
|
||||
// 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_EXPRESSION_HPP_INCLUDED
|
||||
#define BOOST_YAP_EXPRESSION_HPP_INCLUDED
|
||||
|
||||
#include <boost/yap/algorithm.hpp>
|
||||
|
||||
|
||||
namespace boost { namespace yap {
|
||||
|
||||
/** Reference expression template that provides all operator overloads.
|
||||
|
||||
\note Due to a limitation of Doxygen, each of the
|
||||
<code>value()</code>, <code>left()</code>, <code>right()</code>, and
|
||||
operator overloads listed here is a stand-in for three member
|
||||
functions. For each function <code>f</code>, the listing here is:
|
||||
\code return_type f (); \endcode However, there are actually three
|
||||
functions:
|
||||
\code
|
||||
return_type f () const &;
|
||||
return_type f () &;
|
||||
return_type f () &&;
|
||||
\endcode
|
||||
*/
|
||||
template<expr_kind Kind, typename Tuple>
|
||||
struct expression
|
||||
{
|
||||
using tuple_type = Tuple;
|
||||
|
||||
static const expr_kind kind = Kind;
|
||||
|
||||
/** Default constructor. Does nothing. */
|
||||
constexpr expression() {}
|
||||
|
||||
/** Moves \a rhs into the only data mamber, \c elements. */
|
||||
constexpr expression(tuple_type && rhs) :
|
||||
elements(static_cast<tuple_type &&>(rhs))
|
||||
{}
|
||||
|
||||
tuple_type elements;
|
||||
|
||||
/** A convenience member function that dispatches to the free function
|
||||
<code>value()</code>. */
|
||||
constexpr decltype(auto) value() &
|
||||
{
|
||||
return ::boost::yap::value(*this);
|
||||
}
|
||||
|
||||
#ifndef BOOST_YAP_DOXYGEN
|
||||
|
||||
constexpr decltype(auto) value() const &
|
||||
{
|
||||
return ::boost::yap::value(*this);
|
||||
}
|
||||
|
||||
constexpr decltype(auto) value() &&
|
||||
{
|
||||
return ::boost::yap::value(std::move(*this));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** A convenience member function that dispatches to the free function
|
||||
<code>left()</code>. */
|
||||
constexpr decltype(auto) left() & { return ::boost::yap::left(*this); }
|
||||
|
||||
#ifndef BOOST_YAP_DOXYGEN
|
||||
|
||||
constexpr decltype(auto) left() const &
|
||||
{
|
||||
return ::boost::yap::left(*this);
|
||||
}
|
||||
|
||||
constexpr decltype(auto) left() &&
|
||||
{
|
||||
return ::boost::yap::left(std::move(*this));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** A convenience member function that dispatches to the free function
|
||||
<code>right()</code>. */
|
||||
constexpr decltype(auto) right() &
|
||||
{
|
||||
return ::boost::yap::right(*this);
|
||||
}
|
||||
|
||||
#ifndef BOOST_YAP_DOXYGEN
|
||||
|
||||
constexpr decltype(auto) right() const &
|
||||
{
|
||||
return ::boost::yap::right(*this);
|
||||
}
|
||||
|
||||
constexpr decltype(auto) right() &&
|
||||
{
|
||||
return ::boost::yap::right(std::move(*this));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_YAP_USER_ASSIGN_OPERATOR(
|
||||
expression, ::boost::yap::expression) // =
|
||||
BOOST_YAP_USER_SUBSCRIPT_OPERATOR(::boost::yap::expression) // []
|
||||
BOOST_YAP_USER_CALL_OPERATOR(::boost::yap::expression) // ()
|
||||
};
|
||||
|
||||
/** Terminal expression specialization of the reference expression
|
||||
template.
|
||||
|
||||
\note Due to a limitation of Doxygen, the <code>value()</code> member
|
||||
and each of the operator overloads listed here is a stand-in for three
|
||||
member functions. For each function <code>f</code>, the listing here
|
||||
is: \code return_type f (); \endcode However, there are actually three
|
||||
functions:
|
||||
\code
|
||||
return_type f () const &;
|
||||
return_type f () &;
|
||||
return_type f () &&;
|
||||
\endcode
|
||||
*/
|
||||
template<typename T>
|
||||
struct expression<expr_kind::terminal, hana::tuple<T>>
|
||||
{
|
||||
using tuple_type = hana::tuple<T>;
|
||||
|
||||
static const expr_kind kind = expr_kind::terminal;
|
||||
|
||||
/** Default constructor. Does nothing. */
|
||||
constexpr expression() {}
|
||||
|
||||
/** Forwards \a t into \c elements. */
|
||||
constexpr expression(T && t) : elements(static_cast<T &&>(t)) {}
|
||||
|
||||
/** Copies \a rhs into the only data mamber, \c elements. */
|
||||
constexpr expression(hana::tuple<T> const & rhs) : elements(rhs) {}
|
||||
|
||||
/** Moves \a rhs into the only data mamber, \c elements. */
|
||||
constexpr expression(hana::tuple<T> && rhs) : elements(std::move(rhs))
|
||||
{}
|
||||
|
||||
tuple_type elements;
|
||||
|
||||
/** A convenience member function that dispatches to the free function
|
||||
<code>value()</code>. */
|
||||
constexpr decltype(auto) value() &
|
||||
{
|
||||
return ::boost::yap::value(*this);
|
||||
}
|
||||
|
||||
#ifndef BOOST_YAP_DOXYGEN
|
||||
|
||||
constexpr decltype(auto) value() const &
|
||||
{
|
||||
return ::boost::yap::value(*this);
|
||||
}
|
||||
|
||||
constexpr decltype(auto) value() &&
|
||||
{
|
||||
return ::boost::yap::value(std::move(*this));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_YAP_USER_ASSIGN_OPERATOR(
|
||||
expression, ::boost::yap::expression) // =
|
||||
BOOST_YAP_USER_SUBSCRIPT_OPERATOR(::boost::yap::expression) // []
|
||||
BOOST_YAP_USER_CALL_OPERATOR(::boost::yap::expression) // ()
|
||||
};
|
||||
|
||||
#ifndef BOOST_YAP_DOXYGEN
|
||||
|
||||
BOOST_YAP_USER_UNARY_OPERATOR(unary_plus, expression, expression) // +
|
||||
BOOST_YAP_USER_UNARY_OPERATOR(negate, expression, expression) // -
|
||||
BOOST_YAP_USER_UNARY_OPERATOR(dereference, expression, expression) // *
|
||||
BOOST_YAP_USER_UNARY_OPERATOR(complement, expression, expression) // ~
|
||||
BOOST_YAP_USER_UNARY_OPERATOR(address_of, expression, expression) // &
|
||||
BOOST_YAP_USER_UNARY_OPERATOR(logical_not, expression, expression) // !
|
||||
BOOST_YAP_USER_UNARY_OPERATOR(pre_inc, expression, expression) // ++
|
||||
BOOST_YAP_USER_UNARY_OPERATOR(pre_dec, expression, expression) // --
|
||||
BOOST_YAP_USER_UNARY_OPERATOR(post_inc, expression, expression) // ++(int)
|
||||
BOOST_YAP_USER_UNARY_OPERATOR(post_dec, expression, expression) // --(int)
|
||||
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(shift_left, expression, expression) // <<
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(shift_right, expression, expression) // >>
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(multiplies, expression, expression) // *
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(divides, expression, expression) // /
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(modulus, expression, expression) // %
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(plus, expression, expression) // +
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(minus, expression, expression) // -
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(less, expression, expression) // <
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(greater, expression, expression) // >
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(less_equal, expression, expression) // <=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(greater_equal, expression, expression) // >=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(equal_to, expression, expression) // ==
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(not_equal_to, expression, expression) // !=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(logical_or, expression, expression) // ||
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(logical_and, expression, expression) // &&
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(bitwise_and, expression, expression) // &
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(bitwise_or, expression, expression) // |
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(bitwise_xor, expression, expression) // ^
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(comma, expression, expression) // ,
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(mem_ptr, expression, expression) // ->*
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(shift_left_assign, expression, expression) // <<=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(shift_right_assign, expression, expression) // >>=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(multiplies_assign, expression, expression) // *=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(divides_assign, expression, expression) // /=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(modulus_assign, expression, expression) // %=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(plus_assign, expression, expression) // +=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(minus_assign, expression, expression) // -=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(bitwise_and_assign, expression, expression) // &=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(bitwise_or_assign, expression, expression) // |=
|
||||
BOOST_YAP_USER_BINARY_OPERATOR(bitwise_xor_assign, expression, expression) // ^=
|
||||
|
||||
BOOST_YAP_USER_EXPR_IF_ELSE(expression)
|
||||
|
||||
#else
|
||||
|
||||
/** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
|
||||
template<typename Expr>
|
||||
constexpr auto operator+(Expr &&);
|
||||
/** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
|
||||
template<typename Expr>
|
||||
constexpr auto operator-(Expr &&);
|
||||
/** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
|
||||
template<typename Expr>
|
||||
constexpr auto operator*(Expr &&);
|
||||
/** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
|
||||
template<typename Expr>
|
||||
constexpr auto operator~(Expr &&);
|
||||
/** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
|
||||
template<typename Expr>
|
||||
constexpr auto operator&(Expr &&);
|
||||
/** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
|
||||
template<typename Expr>
|
||||
constexpr auto operator!(Expr &&);
|
||||
/** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
|
||||
template<typename Expr>
|
||||
constexpr auto operator++(Expr &&);
|
||||
/** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
|
||||
template<typename Expr>
|
||||
constexpr auto operator--(Expr &&);
|
||||
/** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
|
||||
template<typename Expr>
|
||||
constexpr auto operator++(Expr &&, int);
|
||||
/** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */
|
||||
template<typename Expr>
|
||||
constexpr auto operator--(Expr &&, int);
|
||||
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator<<(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator>>(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator*(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator/(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator%(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator+(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator-(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator<(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator>(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator<=(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator>=(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator==(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator!=(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator||(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator&&(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator&(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator|(LExpr && lhs, RExpr && rhs);
|
||||
/** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */
|
||||
template<typename LExpr, typename RExpr>
|
||||
constexpr auto operator^(LExpr && lhs, RExpr && rhs);
|
||||
|
||||
/** \see BOOST_YAP_USER_EXPR_IF_ELSE for full semantics. */
|
||||
template<typename Expr1, typename Expr2, typename Expr3>
|
||||
constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3);
|
||||
|
||||
#endif
|
||||
|
||||
/** Returns <code>make_expression<boost::yap::expression, Kind>(...)</code>.
|
||||
*/
|
||||
template<expr_kind Kind, typename... T>
|
||||
constexpr auto make_expression(T &&... t)
|
||||
{
|
||||
return make_expression<expression, Kind>(static_cast<T &&>(t)...);
|
||||
}
|
||||
|
||||
/** Returns <code>make_terminal<boost::yap::expression>(t)</code>. */
|
||||
template<typename T>
|
||||
constexpr auto make_terminal(T && t)
|
||||
{
|
||||
return make_terminal<expression>(static_cast<T &&>(t));
|
||||
}
|
||||
|
||||
/** Returns <code>as_expr<boost::yap::expression>(t)</code>. */
|
||||
template<typename T>
|
||||
constexpr decltype(auto) as_expr(T && t)
|
||||
{
|
||||
return as_expr<expression>(static_cast<T &&>(t));
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
320
install/boost_1_75_0/include/boost/yap/print.hpp
Normal file
320
install/boost_1_75_0/include/boost/yap/print.hpp
Normal file
@@ -0,0 +1,320 @@
|
||||
// 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_PRINT_HPP_INCLUDED
|
||||
#define BOOST_YAP_PRINT_HPP_INCLUDED
|
||||
|
||||
#include <boost/yap/algorithm_fwd.hpp>
|
||||
|
||||
#include <boost/hana/for_each.hpp>
|
||||
#include <boost/type_index.hpp>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
namespace boost { namespace yap {
|
||||
|
||||
/** Returns the <code>char const *</code> string for the spelling of the
|
||||
C++ operator associated with \a kind. It returns the special values
|
||||
"ref" and "term" for the non-operator kinds
|
||||
<code>expr_kind::expr_ref</code> amd <code>expr_kind::terminal</code>,
|
||||
respectively.*/
|
||||
inline constexpr char const * op_string(expr_kind kind)
|
||||
{
|
||||
switch (kind) {
|
||||
case expr_kind::expr_ref: return "ref";
|
||||
|
||||
case expr_kind::terminal: return "term";
|
||||
|
||||
case expr_kind::unary_plus: return "+";
|
||||
case expr_kind::negate: return "-";
|
||||
case expr_kind::dereference: return "*";
|
||||
case expr_kind::complement: return "~";
|
||||
case expr_kind::address_of: return "&";
|
||||
case expr_kind::logical_not: return "!";
|
||||
case expr_kind::pre_inc: return "++";
|
||||
case expr_kind::pre_dec: return "--";
|
||||
case expr_kind::post_inc: return "++(int)";
|
||||
case expr_kind::post_dec: return "--(int)";
|
||||
|
||||
case expr_kind::shift_left: return "<<";
|
||||
case expr_kind::shift_right: return ">>";
|
||||
case expr_kind::multiplies: return "*";
|
||||
case expr_kind::divides: return "/";
|
||||
case expr_kind::modulus: return "%";
|
||||
case expr_kind::plus: return "+";
|
||||
case expr_kind::minus: return "-";
|
||||
case expr_kind::less: return "<";
|
||||
case expr_kind::greater: return ">";
|
||||
case expr_kind::less_equal: return "<=";
|
||||
case expr_kind::greater_equal: return ">=";
|
||||
case expr_kind::equal_to: return "==";
|
||||
case expr_kind::not_equal_to: return "!=";
|
||||
case expr_kind::logical_or: return "||";
|
||||
case expr_kind::logical_and: return "&&";
|
||||
case expr_kind::bitwise_and: return "&";
|
||||
case expr_kind::bitwise_or: return "|";
|
||||
case expr_kind::bitwise_xor: return "^";
|
||||
case expr_kind::comma: return ",";
|
||||
case expr_kind::mem_ptr: return "->*";
|
||||
case expr_kind::assign: return "=";
|
||||
case expr_kind::shift_left_assign: return "<<=";
|
||||
case expr_kind::shift_right_assign: return ">>=";
|
||||
case expr_kind::multiplies_assign: return "*=";
|
||||
case expr_kind::divides_assign: return "/=";
|
||||
case expr_kind::modulus_assign: return "%=";
|
||||
case expr_kind::plus_assign: return "+=";
|
||||
case expr_kind::minus_assign: return "-=";
|
||||
case expr_kind::bitwise_and_assign: return "&=";
|
||||
case expr_kind::bitwise_or_assign: return "|=";
|
||||
case expr_kind::bitwise_xor_assign: return "^=";
|
||||
case expr_kind::subscript: return "[]";
|
||||
|
||||
case expr_kind::if_else: return "?:";
|
||||
|
||||
case expr_kind::call: return "()";
|
||||
|
||||
default: return "** ERROR: UNKNOWN OPERATOR! **";
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline std::ostream & print_kind(std::ostream & os, expr_kind kind)
|
||||
{
|
||||
return os << op_string(kind);
|
||||
}
|
||||
|
||||
template<typename T, typename = void_t<>>
|
||||
struct printer
|
||||
{
|
||||
std::ostream & operator()(std::ostream & os, T const &)
|
||||
{
|
||||
return os << "<<unprintable-value>>";
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct printer<
|
||||
T,
|
||||
void_t<decltype(
|
||||
std::declval<std::ostream &>() << std::declval<T const &>())>>
|
||||
{
|
||||
std::ostream & operator()(std::ostream & os, T const & x)
|
||||
{
|
||||
return os << x;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline std::ostream & print_value(std::ostream & os, T const & x)
|
||||
{
|
||||
return printer<T>{}(os, x);
|
||||
}
|
||||
|
||||
template<long long I>
|
||||
inline std::ostream & print_value(std::ostream & os, hana::llong<I>)
|
||||
{
|
||||
return os << I << "_p";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::ostream & print_type(std::ostream & os, hana::tuple<T> const &)
|
||||
{
|
||||
os << typeindex::type_id<T>().pretty_name();
|
||||
if (std::is_const<std::remove_reference_t<T>>::value)
|
||||
os << " const";
|
||||
if (std::is_volatile<std::remove_reference_t<T>>::value)
|
||||
os << " volatile";
|
||||
if (std::is_lvalue_reference<T>::value)
|
||||
os << " &";
|
||||
if (std::is_rvalue_reference<T>::value)
|
||||
os << " &&";
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool is_const_expr_ref(T const &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
template<typename T, template<expr_kind, class> class expr_template>
|
||||
bool is_const_expr_ref(
|
||||
expr_template<expr_kind::expr_ref, hana::tuple<T const *>> const &)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef BOOST_NO_CONSTEXPR_IF
|
||||
|
||||
template<expr_kind Kind>
|
||||
struct print_impl
|
||||
{
|
||||
template<typename Expr>
|
||||
std::ostream & operator()(
|
||||
std::ostream & os,
|
||||
Expr const & expr,
|
||||
int indent,
|
||||
char const * indent_str,
|
||||
bool is_ref = false,
|
||||
bool is_const_ref = false)
|
||||
{
|
||||
for (int i = 0; i < indent; ++i) {
|
||||
os << indent_str;
|
||||
}
|
||||
|
||||
os << "expr<";
|
||||
::boost::yap::detail::print_kind(os, Expr::kind);
|
||||
os << ">";
|
||||
if (is_const_ref)
|
||||
os << " const &";
|
||||
else if (is_ref)
|
||||
os << " &";
|
||||
os << "\n";
|
||||
hana::for_each(
|
||||
expr.elements,
|
||||
[&os, indent, indent_str](auto const & element) {
|
||||
using element_type = decltype(element);
|
||||
constexpr expr_kind kind =
|
||||
detail::remove_cv_ref_t<element_type>::kind;
|
||||
print_impl<kind>{}(os, element, indent + 1, indent_str);
|
||||
});
|
||||
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct print_impl<expr_kind::expr_ref>
|
||||
{
|
||||
template<typename Expr>
|
||||
std::ostream & operator()(
|
||||
std::ostream & os,
|
||||
Expr const & expr,
|
||||
int indent,
|
||||
char const * indent_str,
|
||||
bool is_ref = false,
|
||||
bool is_const_ref = false)
|
||||
{
|
||||
using ref_type = decltype(::boost::yap::deref(expr));
|
||||
constexpr expr_kind ref_kind =
|
||||
detail::remove_cv_ref_t<ref_type>::kind;
|
||||
print_impl<ref_kind>{}(
|
||||
os,
|
||||
::boost::yap::deref(expr),
|
||||
indent,
|
||||
indent_str,
|
||||
true,
|
||||
::boost::yap::detail::is_const_expr_ref(expr));
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct print_impl<expr_kind::terminal>
|
||||
{
|
||||
template<typename Expr>
|
||||
std::ostream & operator()(
|
||||
std::ostream & os,
|
||||
Expr const & expr,
|
||||
int indent,
|
||||
char const * indent_str,
|
||||
bool is_ref = false,
|
||||
bool is_const_ref = false)
|
||||
{
|
||||
for (int i = 0; i < indent; ++i) {
|
||||
os << indent_str;
|
||||
}
|
||||
|
||||
os << "term<";
|
||||
::boost::yap::detail::print_type(os, expr.elements);
|
||||
os << ">[=";
|
||||
::boost::yap::detail::print_value(
|
||||
os, ::boost::yap::value(expr));
|
||||
os << "]";
|
||||
if (is_const_ref)
|
||||
os << " const &";
|
||||
else if (is_ref)
|
||||
os << " &";
|
||||
os << "\n";
|
||||
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template<typename Expr>
|
||||
std::ostream & print_impl(
|
||||
std::ostream & os,
|
||||
Expr const & expr,
|
||||
int indent,
|
||||
char const * indent_str,
|
||||
bool is_ref = false,
|
||||
bool is_const_ref = false)
|
||||
{
|
||||
if constexpr (Expr::kind == expr_kind::expr_ref) {
|
||||
print_impl(
|
||||
os,
|
||||
::boost::yap::deref(expr),
|
||||
indent,
|
||||
indent_str,
|
||||
true,
|
||||
::boost::yap::detail::is_const_expr_ref(expr));
|
||||
} else {
|
||||
for (int i = 0; i < indent; ++i) {
|
||||
os << indent_str;
|
||||
}
|
||||
|
||||
if constexpr (Expr::kind == expr_kind::terminal) {
|
||||
os << "term<";
|
||||
::boost::yap::detail::print_type(os, expr.elements);
|
||||
os << ">[=";
|
||||
::boost::yap::detail::print_value(
|
||||
os, ::boost::yap::value(expr));
|
||||
os << "]";
|
||||
if (is_const_ref)
|
||||
os << " const &";
|
||||
else if (is_ref)
|
||||
os << " &";
|
||||
os << "\n";
|
||||
} else {
|
||||
os << "expr<";
|
||||
::boost::yap::detail::print_kind(os, Expr::kind);
|
||||
os << ">";
|
||||
if (is_const_ref)
|
||||
os << " const &";
|
||||
else if (is_ref)
|
||||
os << " &";
|
||||
os << "\n";
|
||||
hana::for_each(
|
||||
expr.elements,
|
||||
[&os, indent, indent_str](auto const & element) {
|
||||
::boost::yap::detail::print_impl(
|
||||
os, element, indent + 1, indent_str);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif // BOOST_NO_CONSTEXPR_IF
|
||||
}
|
||||
|
||||
/** Prints expression \a expr to stream \a os. Returns \a os. */
|
||||
template<typename Expr>
|
||||
std::ostream & print(std::ostream & os, Expr const & expr)
|
||||
{
|
||||
#ifdef BOOST_NO_CONSTEXPR_IF
|
||||
return detail::print_impl<detail::remove_cv_ref_t<Expr>::kind>{}(
|
||||
os, expr, 0, " ");
|
||||
#else
|
||||
return detail::print_impl(os, expr, 0, " ");
|
||||
#endif
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
829
install/boost_1_75_0/include/boost/yap/user_macros.hpp
Normal file
829
install/boost_1_75_0/include/boost/yap/user_macros.hpp
Normal file
@@ -0,0 +1,829 @@
|
||||
// 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_USER_MACROS_HPP_INCLUDED
|
||||
#define BOOST_YAP_USER_MACROS_HPP_INCLUDED
|
||||
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
|
||||
|
||||
#ifndef BOOST_YAP_DOXYGEN
|
||||
|
||||
// unary
|
||||
#define BOOST_YAP_OPERATOR_unary_plus(...) +(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_negate(...) -(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_dereference(...) *(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_complement(...) ~(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_address_of(...) &(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_logical_not(...) !(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_pre_inc(...) ++(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_pre_dec(...) --(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_post_inc(...) ++(__VA_ARGS__, int)
|
||||
#define BOOST_YAP_OPERATOR_post_dec(...) --(__VA_ARGS__, int)
|
||||
|
||||
// binary
|
||||
#define BOOST_YAP_OPERATOR_shift_left(...) <<(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_shift_right(...) >>(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_multiplies(...) *(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_divides(...) /(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_modulus(...) %(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_plus(...) +(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_minus(...) -(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_less(...) <(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_greater(...) >(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_less_equal(...) <=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_greater_equal(...) >=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_equal_to(...) ==(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_not_equal_to(...) !=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_logical_or(...) ||(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_logical_and(...) &&(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_bitwise_and(...) &(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_bitwise_or(...) |(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_bitwise_xor(...) ^(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_comma(...) ,(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_mem_ptr(...) ->*(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_assign(...) =(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_shift_left_assign(...) <<=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_shift_right_assign(...) >>=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_multiplies_assign(...) *=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_divides_assign(...) /=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_modulus_assign(...) %=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_plus_assign(...) +=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_minus_assign(...) -=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_bitwise_and_assign(...) &=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_bitwise_or_assign(...) |=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_bitwise_xor_assign(...) ^=(__VA_ARGS__)
|
||||
#define BOOST_YAP_OPERATOR_subscript(...) [](__VA_ARGS__)
|
||||
|
||||
#define BOOST_YAP_INDIRECT_CALL(macro) BOOST_PP_CAT(BOOST_YAP_OPERATOR_, macro)
|
||||
|
||||
#endif // BOOST_YAP_DOXYGEN
|
||||
|
||||
|
||||
/** Defines operator overloads for unary operator \a op_name that each take an
|
||||
expression instantiated from \a expr_template and return an expression
|
||||
instantiated from the \a result_expr_template expression template. One
|
||||
overload is defined for each of the qualifiers <code>const &</code>,
|
||||
<code>&</code>, and <code>&&</code>. For the lvalue reference overloads,
|
||||
the argument is captured by reference into the resulting expression. For
|
||||
the rvalue reference overload, the argument is moved into the resulting
|
||||
expression.
|
||||
|
||||
Example:
|
||||
\snippet user_macros_snippets.cpp USER_UNARY_OPERATOR
|
||||
|
||||
\param op_name The operator to be overloaded; this must be one of the \b
|
||||
unary enumerators in <code>expr_kind</code>, without the
|
||||
<code>expr_kind::</code> qualification.
|
||||
|
||||
\param expr_template The expression template to which the overloads apply.
|
||||
\a expr_template must be an \ref ExpressionTemplate.
|
||||
|
||||
\param result_expr_template The expression template to use to instantiate
|
||||
the result expression. \a result_expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
*/
|
||||
#define BOOST_YAP_USER_UNARY_OPERATOR( \
|
||||
op_name, expr_template, result_expr_template) \
|
||||
template<::boost::yap::expr_kind Kind, typename Tuple> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
|
||||
expr_template<Kind, Tuple> const & x) \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail::operand_type_t< \
|
||||
result_expr_template, \
|
||||
expr_template<Kind, Tuple> const &>; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type>; \
|
||||
return result_expr_template< \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
tuple_type>{ \
|
||||
tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(x)}}; \
|
||||
} \
|
||||
template<::boost::yap::expr_kind Kind, typename Tuple> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
|
||||
expr_template<Kind, Tuple> & x) \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail::operand_type_t< \
|
||||
result_expr_template, \
|
||||
expr_template<Kind, Tuple> &>; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type>; \
|
||||
return result_expr_template< \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
tuple_type>{ \
|
||||
tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(x)}}; \
|
||||
} \
|
||||
template<::boost::yap::expr_kind Kind, typename Tuple> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
|
||||
expr_template<Kind, Tuple> && x) \
|
||||
{ \
|
||||
using tuple_type = ::boost::hana::tuple<expr_template<Kind, Tuple>>; \
|
||||
return result_expr_template< \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
tuple_type>{tuple_type{std::move(x)}}; \
|
||||
}
|
||||
|
||||
|
||||
/** Defines operator overloads for binary operator \a op_name that each
|
||||
produce an expression instantiated from the \a expr_template expression
|
||||
template. One overload is defined for each of the qualifiers <code>const
|
||||
&</code>, <code>&</code>, and <code>&&</code>. For the lvalue reference
|
||||
overloads, <code>*this</code> is captured by reference into the resulting
|
||||
expression. For the rvalue reference overload, <code>*this</code> is
|
||||
moved into the resulting expression.
|
||||
|
||||
Note that this does not work for yap::expr_kinds assign, subscript, or
|
||||
call. Use BOOST_YAP_USER_ASSIGN_OPERATOR,
|
||||
BOOST_YAP_USER_SUBSCRIPT_OPERATOR, or BOOST_YAP_USER_CALL_OPERATOR for
|
||||
those, respectively.
|
||||
|
||||
Example:
|
||||
\snippet user_macros_snippets.cpp USER_BINARY_OPERATOR
|
||||
|
||||
\param op_name The operator to be overloaded; this must be one of the \b
|
||||
binary enumerators in <code>expr_kind</code>, except assign, subscript, or
|
||||
call, without the <code>expr_kind::</code> qualification.
|
||||
|
||||
\param expr_template The expression template to which the overloads apply.
|
||||
\a expr_template must be an \ref ExpressionTemplate.
|
||||
|
||||
\param result_expr_template The expression template to use to instantiate
|
||||
the result expression. \a result_expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
*/
|
||||
#define BOOST_YAP_USER_BINARY_OPERATOR( \
|
||||
op_name, expr_template, result_expr_template) \
|
||||
template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
|
||||
expr_template<Kind, Tuple> const & lhs, Expr && rhs) \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail::operand_type_t< \
|
||||
result_expr_template, \
|
||||
expr_template<Kind, Tuple> const &>; \
|
||||
using rhs_type = \
|
||||
::boost::yap::detail::operand_type_t<result_expr_template, Expr>; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
return result_expr_template< \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
tuple_type>{ \
|
||||
tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(lhs), \
|
||||
::boost::yap::detail::make_operand<rhs_type>{}( \
|
||||
static_cast<Expr &&>(rhs))}}; \
|
||||
} \
|
||||
template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
|
||||
expr_template<Kind, Tuple> & lhs, Expr && rhs) \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail::operand_type_t< \
|
||||
result_expr_template, \
|
||||
expr_template<Kind, Tuple> &>; \
|
||||
using rhs_type = \
|
||||
::boost::yap::detail::operand_type_t<result_expr_template, Expr>; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
return result_expr_template< \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
tuple_type>{ \
|
||||
tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(lhs), \
|
||||
::boost::yap::detail::make_operand<rhs_type>{}( \
|
||||
static_cast<Expr &&>(rhs))}}; \
|
||||
} \
|
||||
template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
|
||||
expr_template<Kind, Tuple> && lhs, Expr && rhs) \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail::remove_cv_ref_t< \
|
||||
expr_template<Kind, Tuple> &&>; \
|
||||
using rhs_type = \
|
||||
::boost::yap::detail::operand_type_t<result_expr_template, Expr>; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
return result_expr_template< \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
tuple_type>{ \
|
||||
tuple_type{std::move(lhs), \
|
||||
::boost::yap::detail::make_operand<rhs_type>{}( \
|
||||
static_cast<Expr &&>(rhs))}}; \
|
||||
} \
|
||||
template<typename T, ::boost::yap::expr_kind Kind, typename Tuple> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
|
||||
T && lhs, expr_template<Kind, Tuple> && rhs) \
|
||||
->::boost::yap::detail::free_binary_op_result_t< \
|
||||
result_expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
expr_template<Kind, Tuple> &&> \
|
||||
{ \
|
||||
using result_types = ::boost::yap::detail::free_binary_op_result< \
|
||||
result_expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
expr_template<Kind, Tuple> &&>; \
|
||||
using lhs_type = typename result_types::lhs_type; \
|
||||
using rhs_type = typename result_types::rhs_type; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, std::move(rhs)}}; \
|
||||
} \
|
||||
template<typename T, ::boost::yap::expr_kind Kind, typename Tuple> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
|
||||
T && lhs, expr_template<Kind, Tuple> const & rhs) \
|
||||
->::boost::yap::detail::free_binary_op_result_t< \
|
||||
result_expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
expr_template<Kind, Tuple> const &> \
|
||||
{ \
|
||||
using result_types = ::boost::yap::detail::free_binary_op_result< \
|
||||
result_expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
expr_template<Kind, Tuple> const &>; \
|
||||
using lhs_type = typename result_types::lhs_type; \
|
||||
using rhs_type = typename result_types::rhs_type; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
using rhs_tuple_type = typename result_types::rhs_tuple_type; \
|
||||
return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, \
|
||||
rhs_type{rhs_tuple_type{std::addressof(rhs)}}}}; \
|
||||
} \
|
||||
template<typename T, ::boost::yap::expr_kind Kind, typename Tuple> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \
|
||||
T && lhs, expr_template<Kind, Tuple> & rhs) \
|
||||
->::boost::yap::detail::free_binary_op_result_t< \
|
||||
result_expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
expr_template<Kind, Tuple> &> \
|
||||
{ \
|
||||
using result_types = ::boost::yap::detail::free_binary_op_result< \
|
||||
result_expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
expr_template<Kind, Tuple> &>; \
|
||||
using lhs_type = typename result_types::lhs_type; \
|
||||
using rhs_type = typename result_types::rhs_type; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
using rhs_tuple_type = typename result_types::rhs_tuple_type; \
|
||||
return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, \
|
||||
rhs_type{rhs_tuple_type{std::addressof(rhs)}}}}; \
|
||||
}
|
||||
|
||||
|
||||
/** Defines operator overloads for \a operator=() that each produce an
|
||||
expression instantiated from the \a expr_template expression template.
|
||||
One overload is defined for each of the qualifiers <code>const &</code>,
|
||||
<code>&</code>, and <code>&&</code>. For the lvalue reference overloads,
|
||||
<code>*this</code> is captured by reference into the resulting expression.
|
||||
For the rvalue reference overload, <code>*this</code> is moved into the
|
||||
resulting expression.
|
||||
|
||||
The \a rhs parameter to each of the defined overloads may be any type,
|
||||
including an expression, except that the overloads are constrained by
|
||||
std::enable_if<> not to conflict with the assignment and move assignement
|
||||
operators. If \a rhs is a non-expression, it is wrapped in a terminal
|
||||
expression.
|
||||
|
||||
Example:
|
||||
\snippet user_macros_snippets.cpp USER_ASSIGN_OPERATOR
|
||||
|
||||
\param this_type The type of the class the operator is a member of; this
|
||||
is required to avoid clashing with the assignment and move assignement
|
||||
operators.
|
||||
|
||||
\param expr_template The expression template to use to instantiate the
|
||||
result expression. \a expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
*/
|
||||
#define BOOST_YAP_USER_ASSIGN_OPERATOR(this_type, expr_template) \
|
||||
template< \
|
||||
typename Expr, \
|
||||
typename = std::enable_if_t< \
|
||||
!::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>> \
|
||||
constexpr auto operator=(Expr && rhs) const & \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail:: \
|
||||
operand_type_t<expr_template, this_type const &>; \
|
||||
using rhs_type = \
|
||||
::boost::yap::detail::operand_type_t<expr_template, Expr>; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \
|
||||
tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
|
||||
::boost::yap::detail::make_operand<rhs_type>{}( \
|
||||
static_cast<Expr &&>(rhs))}}; \
|
||||
} \
|
||||
template< \
|
||||
typename Expr, \
|
||||
typename = std::enable_if_t< \
|
||||
!::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>> \
|
||||
constexpr auto operator=(Expr && rhs) & \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail:: \
|
||||
operand_type_t<expr_template, decltype(*this)>; \
|
||||
using rhs_type = \
|
||||
::boost::yap::detail::operand_type_t<expr_template, Expr>; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \
|
||||
tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
|
||||
::boost::yap::detail::make_operand<rhs_type>{}( \
|
||||
static_cast<Expr &&>(rhs))}}; \
|
||||
} \
|
||||
template< \
|
||||
typename Expr, \
|
||||
typename = std::enable_if_t< \
|
||||
!::boost::yap::detail::copy_or_move<this_type, Expr &&>::value>> \
|
||||
constexpr auto operator=(Expr && rhs) && \
|
||||
{ \
|
||||
using rhs_type = \
|
||||
::boost::yap::detail::operand_type_t<expr_template, Expr>; \
|
||||
using tuple_type = ::boost::hana::tuple<this_type, rhs_type>; \
|
||||
return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \
|
||||
tuple_type{std::move(*this), \
|
||||
::boost::yap::detail::make_operand<rhs_type>{}( \
|
||||
static_cast<Expr &&>(rhs))}}; \
|
||||
}
|
||||
|
||||
|
||||
/** Defines operator overloads for \a operator[]() that each produce an
|
||||
expression instantiated from the \a expr_template expression template.
|
||||
One overload is defined for each of the qualifiers <code>const &</code>,
|
||||
<code>&</code>, and <code>&&</code>. For the lvalue reference overloads,
|
||||
<code>*this</code> is captured by reference into the resulting expression.
|
||||
For the rvalue reference overload, <code>*this</code> is moved into the
|
||||
resulting expression.
|
||||
|
||||
The \a rhs parameter to each of the defined overloads may be any type,
|
||||
including an expression, except that the overloads are constrained by
|
||||
std::enable_if<> not to conflict with the assignment and move assignement
|
||||
operators. If \a rhs is a non-expression, it is wrapped in a terminal
|
||||
expression.
|
||||
|
||||
Example:
|
||||
\snippet user_macros_snippets.cpp USER_SUBSCRIPT_OPERATOR
|
||||
|
||||
\param expr_template The expression template to use to instantiate the
|
||||
result expression. \a expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
*/
|
||||
#define BOOST_YAP_USER_SUBSCRIPT_OPERATOR(expr_template) \
|
||||
template<typename Expr> \
|
||||
constexpr auto operator[](Expr && rhs) const & \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail:: \
|
||||
operand_type_t<expr_template, decltype(*this)>; \
|
||||
using rhs_type = \
|
||||
::boost::yap::detail::operand_type_t<expr_template, Expr>; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \
|
||||
tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
|
||||
::boost::yap::detail::make_operand<rhs_type>{}( \
|
||||
static_cast<Expr &&>(rhs))}}; \
|
||||
} \
|
||||
template<typename Expr> \
|
||||
constexpr auto operator[](Expr && rhs) & \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail:: \
|
||||
operand_type_t<expr_template, decltype(*this)>; \
|
||||
using rhs_type = \
|
||||
::boost::yap::detail::operand_type_t<expr_template, Expr>; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \
|
||||
tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
|
||||
::boost::yap::detail::make_operand<rhs_type>{}( \
|
||||
static_cast<Expr &&>(rhs))}}; \
|
||||
} \
|
||||
template<typename Expr> \
|
||||
constexpr auto operator[](Expr && rhs) && \
|
||||
{ \
|
||||
using lhs_type = \
|
||||
::boost::yap::detail::remove_cv_ref_t<decltype(*this)>; \
|
||||
using rhs_type = \
|
||||
::boost::yap::detail::operand_type_t<expr_template, Expr>; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \
|
||||
tuple_type{std::move(*this), \
|
||||
::boost::yap::detail::make_operand<rhs_type>{}( \
|
||||
static_cast<Expr &&>(rhs))}}; \
|
||||
}
|
||||
|
||||
|
||||
/** Defines operator overloads for the call operator taking any number of
|
||||
parameters ("operator()") that each produce an expression instantiated
|
||||
from the \a expr_template expression template. One overload is defined
|
||||
for each of the qualifiers <code>const &</code>, <code>&</code>, and
|
||||
<code>&&</code>. For the lvalue reference overloads, <code>*this</code>
|
||||
is captured by reference into the resulting expression. For the rvalue
|
||||
reference overload, <code>*this</code> is moved into the resulting
|
||||
expression.
|
||||
|
||||
The \a u parameters to each of the defined overloads may be any type,
|
||||
including an expression. Each non-expression is wrapped in a terminal
|
||||
expression.
|
||||
|
||||
Example:
|
||||
\snippet user_macros_snippets.cpp USER_CALL_OPERATOR
|
||||
|
||||
\param expr_template The expression template to use to instantiate the
|
||||
result expression. \a expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
*/
|
||||
#define BOOST_YAP_USER_CALL_OPERATOR(expr_template) \
|
||||
template<typename... U> \
|
||||
constexpr auto operator()(U &&... u) const & \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail:: \
|
||||
operand_type_t<expr_template, decltype(*this)>; \
|
||||
using tuple_type = ::boost::hana::tuple< \
|
||||
lhs_type, \
|
||||
::boost::yap::detail::operand_type_t<expr_template, U>...>; \
|
||||
return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
|
||||
tuple_type{ \
|
||||
::boost::yap::detail::make_operand<lhs_type>{}(*this), \
|
||||
::boost::yap::detail::make_operand< \
|
||||
::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
|
||||
static_cast<U &&>(u))...}}; \
|
||||
} \
|
||||
template<typename... U> \
|
||||
constexpr auto operator()(U &&... u) & \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail:: \
|
||||
operand_type_t<expr_template, decltype(*this)>; \
|
||||
using tuple_type = ::boost::hana::tuple< \
|
||||
lhs_type, \
|
||||
::boost::yap::detail::operand_type_t<expr_template, U>...>; \
|
||||
return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
|
||||
tuple_type{ \
|
||||
::boost::yap::detail::make_operand<lhs_type>{}(*this), \
|
||||
::boost::yap::detail::make_operand< \
|
||||
::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
|
||||
static_cast<U &&>(u))...}}; \
|
||||
} \
|
||||
template<typename... U> \
|
||||
constexpr auto operator()(U &&... u) && \
|
||||
{ \
|
||||
using this_type = \
|
||||
::boost::yap::detail::remove_cv_ref_t<decltype(*this)>; \
|
||||
using tuple_type = ::boost::hana::tuple< \
|
||||
this_type, \
|
||||
::boost::yap::detail::operand_type_t<expr_template, U>...>; \
|
||||
return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
|
||||
tuple_type{ \
|
||||
std::move(*this), \
|
||||
::boost::yap::detail::make_operand< \
|
||||
::boost::yap::detail::operand_type_t<expr_template, U>>{}( \
|
||||
static_cast<U &&>(u))...}}; \
|
||||
}
|
||||
|
||||
|
||||
#ifndef BOOST_YAP_DOXYGEN
|
||||
|
||||
#define BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T(z, n, expr_template) \
|
||||
::boost::yap::detail::operand_type_t<expr_template, BOOST_PP_CAT(U, n)>
|
||||
#define BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND(z, n, expr_template) \
|
||||
::boost::yap::detail::make_operand<::boost::yap::detail::operand_type_t< \
|
||||
expr_template, \
|
||||
BOOST_PP_CAT(U, n)>>{}( \
|
||||
static_cast<BOOST_PP_CAT(U, n) &&>(BOOST_PP_CAT(u, n)))
|
||||
|
||||
#endif
|
||||
|
||||
/** Defines operator overloads for the call operator taking N parameters
|
||||
("operator()(t0, t1, ... tn-1)") that each produce an expression
|
||||
instantiated from the \a expr_template expression template. One overload
|
||||
is defined for each of the qualifiers <code>const &</code>,
|
||||
<code>&</code>, and <code>&&</code>. For the lvalue reference overloads,
|
||||
<code>*this</code> is captured by reference into the resulting expression.
|
||||
For the rvalue reference overload, <code>*this</code> is moved into the
|
||||
resulting expression.
|
||||
|
||||
The \a u parameters to each of the defined overloads may be any type,
|
||||
including an expression. Each non-expression is wrapped in a terminal
|
||||
expression.
|
||||
|
||||
Example:
|
||||
\snippet user_macros_snippets.cpp USER_CALL_OPERATOR
|
||||
|
||||
\param expr_template The expression template to use to instantiate the
|
||||
result expression. \a expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
|
||||
\param n The number of parameters accepted by the operator() overloads. n
|
||||
must be <= BOOST_PP_LIMIT_REPEAT.
|
||||
*/
|
||||
#define BOOST_YAP_USER_CALL_OPERATOR_N(expr_template, n) \
|
||||
template<BOOST_PP_ENUM_PARAMS(n, typename U)> \
|
||||
constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) const & \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail:: \
|
||||
operand_type_t<expr_template, decltype(*this)>; \
|
||||
using tuple_type = ::boost::hana::tuple< \
|
||||
lhs_type, \
|
||||
BOOST_PP_ENUM( \
|
||||
n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \
|
||||
return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
|
||||
tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
|
||||
BOOST_PP_ENUM( \
|
||||
n, \
|
||||
BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \
|
||||
expr_template)}}; \
|
||||
} \
|
||||
template<BOOST_PP_ENUM_PARAMS(n, typename U)> \
|
||||
constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) & \
|
||||
{ \
|
||||
using lhs_type = ::boost::yap::detail:: \
|
||||
operand_type_t<expr_template, decltype(*this)>; \
|
||||
using tuple_type = ::boost::hana::tuple< \
|
||||
lhs_type, \
|
||||
BOOST_PP_ENUM( \
|
||||
n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \
|
||||
return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
|
||||
tuple_type{::boost::yap::detail::make_operand<lhs_type>{}(*this), \
|
||||
BOOST_PP_ENUM( \
|
||||
n, \
|
||||
BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \
|
||||
expr_template)}}; \
|
||||
} \
|
||||
template<BOOST_PP_ENUM_PARAMS(n, typename U)> \
|
||||
constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) && \
|
||||
{ \
|
||||
using this_type = \
|
||||
::boost::yap::detail::remove_cv_ref_t<decltype(*this)>; \
|
||||
using tuple_type = ::boost::hana::tuple< \
|
||||
this_type, \
|
||||
BOOST_PP_ENUM( \
|
||||
n, BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T, expr_template)>; \
|
||||
return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \
|
||||
tuple_type{std::move(*this), \
|
||||
BOOST_PP_ENUM( \
|
||||
n, \
|
||||
BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \
|
||||
expr_template)}}; \
|
||||
}
|
||||
|
||||
|
||||
/** Defines a 3-parameter function <code>if_else()</code> that acts as an
|
||||
analogue to the ternary operator (<code>?:</code>), since the ternary
|
||||
operator is not user-overloadable. The return type of
|
||||
<code>if_else()</code> is an expression instantiated from the \a
|
||||
expr_template expression template.
|
||||
|
||||
At least one parameter to <code>if_else()</code> must be an expression.
|
||||
|
||||
For each parameter E passed to <code>if_else()</code>, if E is an rvalue,
|
||||
E is moved into the result, and otherwise E is captured by reference into
|
||||
the result.
|
||||
|
||||
Example:
|
||||
\snippet user_macros_snippets.cpp USER_EXPR_IF_ELSE
|
||||
|
||||
\param expr_template The expression template to use to instantiate the
|
||||
result expression. \a expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
*/
|
||||
#define BOOST_YAP_USER_EXPR_IF_ELSE(expr_template) \
|
||||
template<typename Expr1, typename Expr2, typename Expr3> \
|
||||
constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \
|
||||
->::boost::yap::detail:: \
|
||||
ternary_op_result_t<expr_template, Expr1, Expr2, Expr3> \
|
||||
{ \
|
||||
using result_types = ::boost::yap::detail:: \
|
||||
ternary_op_result<expr_template, Expr1, Expr2, Expr3>; \
|
||||
using cond_type = typename result_types::cond_type; \
|
||||
using then_type = typename result_types::then_type; \
|
||||
using else_type = typename result_types::else_type; \
|
||||
using tuple_type = \
|
||||
::boost::hana::tuple<cond_type, then_type, else_type>; \
|
||||
return {tuple_type{::boost::yap::detail::make_operand<cond_type>{}( \
|
||||
static_cast<Expr1 &&>(expr1)), \
|
||||
::boost::yap::detail::make_operand<then_type>{}( \
|
||||
static_cast<Expr2 &&>(expr2)), \
|
||||
::boost::yap::detail::make_operand<else_type>{}( \
|
||||
static_cast<Expr3 &&>(expr3))}}; \
|
||||
}
|
||||
|
||||
|
||||
/** Defines a function <code>if_else()</code> that acts as an analogue to the
|
||||
ternary operator (<code>?:</code>), since the ternary operator is not
|
||||
user-overloadable. The return type of <code>if_else()</code> is an
|
||||
expression instantiated from the \a expr_template expression template.
|
||||
|
||||
Each parameter to <code>if_else()</code> may be any type that is \b not an
|
||||
expression. At least on parameter must be a type <code>T</code> for which
|
||||
\code udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value
|
||||
\endcode is true. Each parameter is wrapped in a terminal expression.
|
||||
|
||||
Example:
|
||||
\snippet user_macros_snippets.cpp USER_UDT_ANY_IF_ELSE
|
||||
|
||||
\param expr_template The expression template to use to instantiate the
|
||||
result expression. \a expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
|
||||
\param udt_trait A trait template to use to constrain which types are
|
||||
accepted as template parameters to <code>if_else()</code>.
|
||||
*/
|
||||
#define BOOST_YAP_USER_UDT_ANY_IF_ELSE(expr_template, udt_trait) \
|
||||
template<typename Expr1, typename Expr2, typename Expr3> \
|
||||
constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \
|
||||
->::boost::yap::detail::udt_any_ternary_op_result_t< \
|
||||
expr_template, \
|
||||
Expr1, \
|
||||
Expr2, \
|
||||
Expr3, \
|
||||
udt_trait> \
|
||||
{ \
|
||||
using result_types = ::boost::yap::detail::udt_any_ternary_op_result< \
|
||||
expr_template, \
|
||||
Expr1, \
|
||||
Expr2, \
|
||||
Expr3, \
|
||||
udt_trait>; \
|
||||
using cond_type = typename result_types::cond_type; \
|
||||
using then_type = typename result_types::then_type; \
|
||||
using else_type = typename result_types::else_type; \
|
||||
using tuple_type = \
|
||||
::boost::hana::tuple<cond_type, then_type, else_type>; \
|
||||
return {tuple_type{::boost::yap::detail::make_operand<cond_type>{}( \
|
||||
static_cast<Expr1 &&>(expr1)), \
|
||||
::boost::yap::detail::make_operand<then_type>{}( \
|
||||
static_cast<Expr2 &&>(expr2)), \
|
||||
::boost::yap::detail::make_operand<else_type>{}( \
|
||||
static_cast<Expr3 &&>(expr3))}}; \
|
||||
}
|
||||
|
||||
|
||||
/** Defines a free/non-member operator overload for unary operator \a op_name
|
||||
that produces an expression instantiated from the \a expr_template
|
||||
expression template.
|
||||
|
||||
The parameter to the defined operator overload may be any type that is \b
|
||||
not an expression and for which \code
|
||||
udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
|
||||
true. The parameter is wrapped in a terminal expression.
|
||||
|
||||
Example:
|
||||
\snippet user_macros_snippets.cpp USER_UDT_UNARY_OPERATOR
|
||||
|
||||
\param op_name The operator to be overloaded; this must be one of the \b
|
||||
unary enumerators in <code>expr_kind</code>, without the
|
||||
<code>expr_kind::</code> qualification.
|
||||
|
||||
\param expr_template The expression template to use to instantiate the
|
||||
result expression. \a expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
|
||||
\param udt_trait A trait template to use to constrain which types are
|
||||
accepted as template parameters to the defined operator overload.
|
||||
*/
|
||||
#define BOOST_YAP_USER_UDT_UNARY_OPERATOR(op_name, expr_template, udt_trait) \
|
||||
template<typename T> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && x) \
|
||||
->::boost::yap::detail::udt_unary_op_result_t< \
|
||||
expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
udt_trait> \
|
||||
{ \
|
||||
using result_types = ::boost::yap::detail::udt_unary_op_result< \
|
||||
expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
udt_trait>; \
|
||||
using x_type = typename result_types::x_type; \
|
||||
using tuple_type = ::boost::hana::tuple<x_type>; \
|
||||
return {tuple_type{x_type{static_cast<T &&>(x)}}}; \
|
||||
}
|
||||
|
||||
|
||||
/** Defines a free/non-member operator overload for binary operator \a op_name
|
||||
that produces an expression instantiated from the \a expr_template
|
||||
expression template.
|
||||
|
||||
The \a lhs parameter to the defined operator overload may be any type that
|
||||
is \b not an expression and for which \code
|
||||
t_udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
|
||||
true. The parameter is wrapped in a terminal expression.
|
||||
|
||||
The \a rhs parameter to the defined operator overload may be any type that
|
||||
is \b not an expression and for which \code
|
||||
u_udt_trait<std::remove_cv_t<std::remove_reference_t<U>>>::value \endcode is
|
||||
true. The parameter is wrapped in a terminal expression.
|
||||
|
||||
Example:
|
||||
\snippet user_macros_snippets.cpp USER_UDT_UDT_BINARY_OPERATOR
|
||||
|
||||
\param op_name The operator to be overloaded; this must be one of the \b
|
||||
binary enumerators in <code>expr_kind</code>, without the
|
||||
<code>expr_kind::</code> qualification.
|
||||
|
||||
\param expr_template The expression template to use to instantiate the
|
||||
result expression. \a expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
|
||||
\param t_udt_trait A trait template to use to constrain which types are
|
||||
accepted as \a T template parameters to the defined operator overload.
|
||||
|
||||
\param u_udt_trait A trait template to use to constrain which types are
|
||||
accepted as \a U template parameters to the defined operator overload.
|
||||
*/
|
||||
#define BOOST_YAP_USER_UDT_UDT_BINARY_OPERATOR( \
|
||||
op_name, expr_template, t_udt_trait, u_udt_trait) \
|
||||
template<typename T, typename U> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \
|
||||
->::boost::yap::detail::udt_udt_binary_op_result_t< \
|
||||
expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
U, \
|
||||
t_udt_trait, \
|
||||
u_udt_trait> \
|
||||
{ \
|
||||
using result_types = ::boost::yap::detail::udt_udt_binary_op_result< \
|
||||
expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
U, \
|
||||
t_udt_trait, \
|
||||
u_udt_trait>; \
|
||||
using lhs_type = typename result_types::lhs_type; \
|
||||
using rhs_type = typename result_types::rhs_type; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
return {tuple_type{ \
|
||||
lhs_type{static_cast<T &&>(lhs)}, \
|
||||
rhs_type{static_cast<U &&>(rhs)}, \
|
||||
}}; \
|
||||
}
|
||||
|
||||
|
||||
/** Defines a free/non-member operator overload for binary operator \a op_name
|
||||
that produces an expression instantiated from the \a expr_template
|
||||
expression template.
|
||||
|
||||
The \a lhs and \a rhs parameters to the defined operator overload may be any
|
||||
types that are \b not expressions. Each parameter is wrapped in a terminal
|
||||
expression.
|
||||
|
||||
At least one of the parameters to the defined operator overload must be a
|
||||
type \c T for which \code
|
||||
udt_trait<std::remove_cv_t<std::remove_reference_t<T>>>::value \endcode is
|
||||
true.
|
||||
|
||||
Example:
|
||||
\snippet user_macros_snippets.cpp USER_UDT_ANY_BINARY_OPERATOR
|
||||
|
||||
\param op_name The operator to be overloaded; this must be one of the \b
|
||||
binary enumerators in <code>expr_kind</code>, without the
|
||||
<code>expr_kind::</code> qualification.
|
||||
|
||||
\param expr_template The expression template to use to instantiate the
|
||||
result expression. \a expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
|
||||
\param udt_trait A trait template to use to constrain which types are
|
||||
accepted as template parameters to the defined operator overload.
|
||||
*/
|
||||
#define BOOST_YAP_USER_UDT_ANY_BINARY_OPERATOR( \
|
||||
op_name, expr_template, udt_trait) \
|
||||
template<typename T, typename U> \
|
||||
constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)(T && lhs, U && rhs) \
|
||||
->::boost::yap::detail::udt_any_binary_op_result_t< \
|
||||
expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
U, \
|
||||
udt_trait> \
|
||||
{ \
|
||||
using result_types = ::boost::yap::detail::udt_any_binary_op_result< \
|
||||
expr_template, \
|
||||
::boost::yap::expr_kind::op_name, \
|
||||
T, \
|
||||
U, \
|
||||
udt_trait>; \
|
||||
using lhs_type = typename result_types::lhs_type; \
|
||||
using rhs_type = typename result_types::rhs_type; \
|
||||
using tuple_type = ::boost::hana::tuple<lhs_type, rhs_type>; \
|
||||
return {tuple_type{lhs_type{static_cast<T &&>(lhs)}, \
|
||||
rhs_type{static_cast<U &&>(rhs)}}}; \
|
||||
}
|
||||
|
||||
|
||||
/** Defines user defined literal template that creates literal placeholders
|
||||
instantiated from the \a expr_template expression template. It is
|
||||
recommended that you put this in its own namespace.
|
||||
|
||||
\param expr_template The expression template to use to instantiate the
|
||||
result expression. \a expr_template must be an \ref
|
||||
ExpressionTemplate.
|
||||
*/
|
||||
#define BOOST_YAP_USER_LITERAL_PLACEHOLDER_OPERATOR(expr_template) \
|
||||
template<char... c> \
|
||||
constexpr auto operator"" _p() \
|
||||
{ \
|
||||
using i = ::boost::hana::llong< \
|
||||
::boost::hana::ic_detail::parse<sizeof...(c)>({c...})>; \
|
||||
static_assert(1 <= i::value, "Placeholders must be >= 1."); \
|
||||
return expr_template< \
|
||||
::boost::yap::expr_kind::terminal, \
|
||||
::boost::hana::tuple<::boost::yap::placeholder<i::value>>>{}; \
|
||||
}
|
||||
|
||||
#endif
|
||||
13
install/boost_1_75_0/include/boost/yap/yap.hpp
Normal file
13
install/boost_1_75_0/include/boost/yap/yap.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
// 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_YAP_HPP_INCLUDED
|
||||
#define BOOST_YAP_YAP_HPP_INCLUDED
|
||||
|
||||
|
||||
#include <boost/yap/algorithm.hpp>
|
||||
#include <boost/yap/expression.hpp>
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user