diff --git a/third-party/boost_1_72_0/boost/yap b/third-party/boost_1_72_0/boost/yap new file mode 120000 index 0000000..6c04e8e --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap @@ -0,0 +1 @@ +yap_dev \ No newline at end of file diff --git a/third-party/boost_1_72_0/boost/yap_1_72_bug/algorithm.hpp b/third-party/boost_1_72_0/boost/yap_1_72_bug/algorithm.hpp new file mode 100644 index 0000000..97a27cb --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_1_72_bug/algorithm.hpp @@ -0,0 +1,727 @@ +// 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 +#include +#include + +#include +#include + + +namespace boost { namespace yap { + +#ifdef BOOST_NO_CONSTEXPR_IF + + namespace detail { + + template + struct deref_impl + { + decltype(auto) operator()(Expr && expr) + { + return std::move(*expr.elements[hana::llong_c<0>]); + } + }; + + template + struct deref_impl + { + decltype(auto) operator()(Expr && expr) + { + return *expr.elements[hana::llong_c<0>]; + } + }; + } + +#endif + + /** "Dereferences" a reference-expression, forwarding its referent to + the caller. */ + template + decltype(auto) deref(Expr && expr) + { + static_assert( + is_expr::value, "deref() is only defined for expressions."); + + static_assert( + detail::remove_cv_ref_t::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::value && + !std::is_const>::value > + {}(static_cast(expr)); +#else + using namespace hana::literals; + if constexpr ( + std::is_rvalue_reference::value && + !std::is_const>::value) { + return std::move(*expr.elements[0_c]); + } else { + return *expr.elements[0_c]; + } +#endif + } + + namespace detail { + + template + struct lvalue_ref_ith_element + : std::is_lvalue_reference()[hana::llong{}])> + { + }; + +#ifdef BOOST_NO_CONSTEXPR_IF + + template + 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> + { + decltype(auto) operator()(T && x) + { + return ::boost::yap::detail::value_impl( + ::boost::yap::deref(static_cast(x))); + } + }; + + template + struct value_expr_impl + { + decltype(auto) operator()(T && x) + { + return x.elements[hana::llong_c<0>]; + } + }; + + template + struct value_expr_impl + { + decltype(auto) operator()(T && x) + { + return std::move(x.elements[hana::llong_c<0>]); + } + }; + + template + struct value_expr_impl< + T, + false, + ValueOfTerminalsOnly, + false, + IsLvalueRef> + { + decltype(auto) operator()(T && x) { return static_cast(x); } + }; + + template + struct value_impl_t + { + decltype(auto) operator()(T && x) + { + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + constexpr detail::expr_arity arity = detail::arity_of(); + 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::value || + detail::lvalue_ref_ith_element< + decltype(x.elements), + 0>::value > {}(static_cast(x)); + } + }; + + template + struct value_impl_t + { + decltype(auto) operator()(T && x) { return static_cast(x); } + }; + + template + decltype(auto) value_impl(T && x) + { + return detail:: + value_impl_t::value, ValueOfTerminalsOnly>{}( + static_cast(x)); + } + +#else + + template + decltype(auto) value_impl(T && x) + { + if constexpr (is_expr::value) { + using namespace hana::literals; + constexpr expr_kind kind = remove_cv_ref_t::kind; + constexpr expr_arity arity = arity_of(); + if constexpr (kind == expr_kind::expr_ref) { + return value_impl( + ::boost::yap::deref(static_cast(x))); + } else if constexpr ( + kind == expr_kind::terminal || + (!ValueOfTerminalsOnly && arity == expr_arity::one)) { + if constexpr ( + std::is_lvalue_reference::value || + detail:: + lvalue_ref_ith_element{}) { + return x.elements[0_c]; + } else { + return std::move(x.elements[0_c]); + } + } else { + return static_cast(x); + } + } else { + return static_cast(x); + } + } + +#endif + } + + /** Forwards the sole element of \a x to the caller, possibly calling + deref() 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 + value(deref(x)). + + - 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 + decltype(auto) value(T && x) + { + return detail::value_impl(static_cast(x)); + } + +#ifdef BOOST_NO_CONSTEXPR_IF + + template + decltype(auto) get(Expr && expr, I const & i); + + namespace detail { + + template + struct get_impl; + + template + struct get_impl + { + decltype(auto) operator()(Expr && expr, hana::llong i) + { + return ::boost::yap::get( + ::boost::yap::deref(static_cast(expr)), i); + } + }; + + template + struct get_impl + { + decltype(auto) operator()(Expr && expr, hana::llong i) + { + return expr.elements[i]; + } + }; + + template + struct get_impl + { + decltype(auto) operator()(Expr && expr, hana::llong i) + { + return std::move(expr.elements[i]); + } + }; + } + +#endif + + /** Forwards the i-th element of \a expr to the caller. If \a + expr is a reference expression, the result is get(deref(expr), + i). + + \note get() is only valid if \a Expr is an expression. + */ + template + decltype(auto) get(Expr && expr, I const & i) + { + static_assert( + is_expr::value, "get() is only defined for expressions."); + static_assert( + hana::IntegralConstant::value, + "'i' must be an IntegralConstant"); + + constexpr expr_kind kind = detail::remove_cv_ref_t::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::value>{}(static_cast(expr), i); +#else + using namespace hana::literals; + if constexpr (kind == expr_kind::expr_ref) { + return ::boost::yap::get( + ::boost::yap::deref(static_cast(expr)), i); + } else { + if constexpr (std::is_lvalue_reference::value) { + return expr.elements[i]; + } else { + return std::move(expr.elements[i]); + } + } +#endif + } + + /** Returns get(expr, boost::hana::llong_c). */ + template + decltype(auto) get_c(Expr && expr) + { + return ::boost::yap::get(static_cast(expr), hana::llong_c); + } + + /** Returns the left operand in a binary operator expression. + + Equivalent to get(expr, 0_c). + + \note left() is only valid if \a Expr is a binary + operator expression. + */ + template + decltype(auto) left(Expr && expr) + { + using namespace hana::literals; + return ::boost::yap::get(static_cast(expr), 0_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + static_assert( + kind == expr_kind::expr_ref || + detail::arity_of() == detail::expr_arity::two, + "left() is only defined for binary expressions."); + } + + /** Returns the right operand in a binary operator expression. + + Equivalent to get(expr, 1_c). + + \note right() is only valid if \a Expr is a binary + operator expression. + */ + template + decltype(auto) right(Expr && expr) + { + using namespace hana::literals; + return ::boost::yap::get(static_cast(expr), 1_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + static_assert( + kind == expr_kind::expr_ref || + detail::arity_of() == detail::expr_arity::two, + "right() is only defined for binary expressions."); + } + + /** Returns the condition expression in an if_else expression. + + Equivalent to get(expr, 0_c). + + \note cond() is only valid if \a Expr is an + expr_kind::if_else expression. + */ + template + decltype(auto) cond(Expr && expr) + { + using namespace hana::literals; + return ::boost::yap::get(static_cast(expr), 0_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::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 get(expr, 1_c). + + \note then() is only valid if \a Expr is an + expr_kind::if_else expression. + */ + template + decltype(auto) then(Expr && expr) + { + using namespace hana::literals; + return ::boost::yap::get(static_cast(expr), 1_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::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 get(expr, 2_c). + + \note else_() is only valid if \a Expr is an + expr_kind::if_else expression. + */ + template + decltype(auto) else_(Expr && expr) + { + using namespace hana::literals; + return ::boost::yap::get(static_cast(expr), 2_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::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 get(expr, 0). + + \note callable() is only valid if \a Expr is an + expr_kind::call expression. + */ + template + decltype(auto) callable(Expr && expr) + { + return ::boost::yap::get(static_cast(expr), hana::llong_c<0>); + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + static_assert( + kind == expr_kind::expr_ref || + detail::arity_of() == detail::expr_arity::n, + "callable() is only defined for call expressions."); + } + + /** Returns the i-th argument expression in a call expression. + + Equivalent to get(expr, i + 1). + + \note argument() is only valid if \a Expr is an + expr_kind::call expression. + */ + template + decltype(auto) argument(Expr && expr, hana::llong i) + { + return ::boost::yap::get( + static_cast(expr), hana::llong_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + static_assert( + kind == expr_kind::expr_ref || + detail::arity_of() == 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 make_expression() is only valid if the number of + parameters passed is appropriate for \a Kind. + */ + template< + template class ExprTemplate, + expr_kind Kind, + typename... T> + auto make_expression(T &&... t) + { + constexpr detail::expr_arity arity = detail::arity_of(); + 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...>; + return ExprTemplate{tuple_type{ + detail::make_operand>{}( + static_cast(t))...}}; + } + + /** Makes a new terminal expression instantiated from the expression + template \a ExprTemplate, with the given value as its sole element. + + \note make_terminal() is only valid if \a T is \b not + an expression. + */ + template class ExprTemplate, typename T> + auto make_terminal(T && t) + { + static_assert( + !is_expr::value, + "make_terminal() is only defined for non expressions."); + using result_type = detail::operand_type_t; + using tuple_type = decltype(std::declval().elements); + return result_type{tuple_type{static_cast(t)}}; + } + +#ifdef BOOST_NO_CONSTEXPR_IF + + namespace detail { + + template< + template class ExprTemplate, + typename T, + bool IsExpr> + struct as_expr_impl + { + decltype(auto) operator()(T && t) { return static_cast(t); } + }; + + template class ExprTemplate, typename T> + struct as_expr_impl + { + decltype(auto) operator()(T && t) + { + return make_terminal(static_cast(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 class ExprTemplate, typename T> + decltype(auto) as_expr(T && t) + { +#ifdef BOOST_NO_CONSTEXPR_IF + return detail::as_expr_impl::value>{}( + static_cast(t)); +#else + if constexpr (is_expr::value) { + return static_cast(t); + } else { + return make_terminal(static_cast(t)); + } +#endif + } + + /** A callable type that evaluates its contained expression when called. + + \see make_expression_function() + */ + template + struct expression_function + { + template + decltype(auto) operator()(U &&... u) + { + return ::boost::yap::evaluate(expr, static_cast(u)...); + } + + Expr expr; + }; + + namespace detail { + + template + 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 make_expression_function() is only valid if \a + Expr is an expression. + */ + template + auto make_expression_function(Expr && expr) + { + static_assert( + is_expr::value, + "make_expression_function() is only defined for expressions."); + using stored_type = + detail::operand_type_t; + return expression_function{ + detail::make_operand{}(static_cast(expr))}; + } +}} + +#include + +namespace boost { namespace yap { + + /** Returns a transform object that replaces placeholders within an + expression with the given values. + */ + template + auto replacements(T &&... t) + { + return detail::placeholder_transform_t(static_cast(t)...); + } + + /** Returns \a expr with the placeholders replaced by YAP terminals + containing the given values. + + \note replace_placeholders(expr, t...) is only valid if + \a expr is an expression, and max_p <= sizeof...(t), + where max_p is the maximum placeholder index in \a expr. + */ + template + decltype(auto) replace_placeholders(Expr && expr, T &&... t) + { + static_assert( + is_expr::value, + "evaluate() is only defined for expressions."); + return transform( + static_cast(expr), replacements(static_cast(t)...)); + } + + /** Returns a transform object that evaluates an expression using the + built-in semantics. The transform replaces any placeholders with the + given values. + */ + template + inline auto evaluation(T &&... t) + { + return detail::evaluation_transform_t(static_cast(t)...); + } + + /** Evaluates \a expr using the built-in semantics, replacing any + placeholders with the given values. + + \note evaluate(expr) is only valid if \a expr is an + expression. + */ + template + decltype(auto) evaluate(Expr && expr, T &&... t) + { + static_assert( + is_expr::value, + "evaluate() is only defined for expressions."); + return transform( + static_cast(expr), evaluation(static_cast(t)...)); + } + + namespace detail { + + template + constexpr auto make_transform_tuple(Transforms &... transforms) + { + return hana::tuple{&transforms...}; + } + + template + struct transform_ + { + template + 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::kind; + return detail:: + transform_impl{}( + static_cast(expr), transform_tuple); + } + }; + } + + /** Returns the result of transforming (all or part of) \a expr using + whatever overloads of Transform::operator() 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 + constexpr decltype(auto) + transform(Expr && expr, Transform && transform, Transforms &&... transforms) + { + static_assert( + is_expr::value, + "transform() is only defined for expressions."); + return detail::transform_{}( + static_cast(expr), transform, transforms...); + } + + /** Returns the result of transforming \a expr using whichever overload of + Transform::operator() best matches \a expr. If no + overload of Transform::operator() 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 + decltype(auto) transform_strict( + Expr && expr, Transform && transform, Transforms &&... transforms) + { + static_assert( + is_expr::value, + "transform() is only defined for expressions."); + return detail::transform_{}( + static_cast(expr), transform, transforms...); + } + +}} + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_1_72_bug/algorithm_fwd.hpp b/third-party/boost_1_72_0/boost/yap_1_72_bug/algorithm_fwd.hpp new file mode 100644 index 0000000..96b0f4c --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_1_72_bug/algorithm_fwd.hpp @@ -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 + +#include +#include +#include + + +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 + struct placeholder : hana::llong + { + }; + +#ifdef BOOST_YAP_DOXYGEN + + /** A metafunction that evaluates to std::true_type if \a Expr is an + Expression, and std::false_type otherwise. */ + template + struct is_expr; + +#else + + template + struct expression; + + namespace detail { + + // void_t + + template + using void_t = void; + + // remove_cv_ref + + template + struct remove_cv_ref : std::remove_cv> + { + }; + + template + using remove_cv_ref_t = typename remove_cv_ref::type; + } + + template< + typename Expr, + typename = detail::void_t<>, + typename = detail::void_t<>> + struct is_expr : std::false_type + { + }; + + template + struct is_expr< + Expr, + detail::void_t::kind)>, + detail::void_t().elements)>> + : std::integral_constant< + bool, + std::is_same< + std::remove_cv_t::kind)>, + expr_kind>::value && + hana::is_a< + hana::tuple_tag, + decltype(std::declval().elements)>> + { + }; + +#endif // BOOST_YAP_DOXYGEN + + /** A convenience alias for a terminal expression holding a \a T, + instantiated from expression template \a expr_template. */ + template class expr_template, typename T> + using terminal = expr_template>; + + /** A convenience alias for a reference expression holding an expression + \a T, instantiated from expression template \a expr_template. */ + template class expr_template, typename T> + using expression_ref = expr_template< + expr_kind::expr_ref, + hana::tuple *>>; + +#ifndef BOOST_YAP_DOXYGEN + + template + decltype(auto) evaluate(Expr && expr, T &&... t); + + template + constexpr decltype(auto) transform( + Expr && expr, Transform && transform, Transforms &&... transforms); + + template + decltype(auto) transform_strict( + Expr && expr, Transform && transform, Transforms &&... transforms); + + template + decltype(auto) deref(T && x); + + template + decltype(auto) value(Expr && expr); + +#endif // BOOST_YAP_DOXYGEN + + namespace literals { + + /** Creates literal placeholders. Placeholder indices are 1-based. */ + template + constexpr auto operator"" _p() + { + using i = hana::llong({c...})>; + static_assert(1 <= i::value, "Placeholders must be >= 1."); + return expression< + expr_kind::terminal, + hana::tuple>>{}; + } + } + + /** Used as the tag-type passed to a transform function written in the + tag-transform form. */ + template + 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 + struct minimal_expr + { + static expr_kind const kind = Kind; + Tuple elements; + }; + +}} + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_1_72_bug/config.hpp b/third-party/boost_1_72_0/boost/yap_1_72_bug/config.hpp new file mode 100644 index 0000000..ec067de --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_1_72_bug/config.hpp @@ -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 diff --git a/third-party/boost_1_72_0/boost/yap_1_72_bug/detail/algorithm.hpp b/third-party/boost_1_72_0/boost/yap_1_72_bug/detail/algorithm.hpp new file mode 100644 index 0000000..072ce05 --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_1_72_bug/detail/algorithm.hpp @@ -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 + +#include +#include + +#include +#include + + +namespace boost { namespace yap { namespace detail { + + // static_const + + template + struct static_const + { + static constexpr T value{}; + }; + + template + constexpr T static_const::value; + + + // partial_decay + + template + struct partial_decay + { + using type = T; + }; + + template + struct partial_decay + { + using type = T *; + }; + template + struct partial_decay + { + using type = T *; + }; + + template + struct partial_decay + { + using type = T *; + }; + template + struct partial_decay + { + using type = T *; + }; + + template + struct partial_decay + { + using type = R (*)(A...); + }; + template + struct partial_decay + { + using type = R (*)(A..., ...); + }; + + template + struct partial_decay + { + using type = R (*)(A...); + }; + template + struct partial_decay + { + using type = R (*)(A..., ...); + }; + + template + struct partial_decay + { + using type = R (*)(A...); + }; + template + struct partial_decay + { + using type = R (*)(A..., ...); + }; + + + // operand_value_type_phase_1 + + template< + typename T, + typename U = typename detail::partial_decay::type, + bool AddRValueRef = std::is_same::value && !std::is_const::value> + struct operand_value_type_phase_1; + + template + struct operand_value_type_phase_1 + { + using type = U &&; + }; + + template + struct operand_value_type_phase_1 + { + using type = U; + }; + + + // expr_ref + + template class ExprTemplate, typename T> + struct expr_ref + { + using type = expression_ref; + }; + + template class ExprTemplate, typename Tuple> + struct expr_ref &> + { + using type = ExprTemplate; + }; + + template class ExprTemplate, typename Tuple> + struct expr_ref< + ExprTemplate, + ExprTemplate const &> + { + using type = ExprTemplate; + }; + + template class ExprTemplate, typename T> + using expr_ref_t = typename expr_ref::type; + + template class ExprTemplate, typename T> + struct expr_ref_tuple; + + template class ExprTemplate, typename Tuple> + struct expr_ref_tuple< + ExprTemplate, + ExprTemplate> + { + using type = Tuple; + }; + + template class ExprTemplate, typename T> + using expr_ref_tuple_t = typename expr_ref_tuple::type; + + + // operand_type + + template< + template class ExprTemplate, + typename T, + typename U = typename operand_value_type_phase_1::type, + bool RemoveRefs = std::is_rvalue_reference::value, + bool IsExpr = is_expr::value, + bool IsLRef = std::is_lvalue_reference::value> + struct operand_type; + + template< + template class ExprTemplate, + typename T, + typename U, + bool RemoveRefs> + struct operand_type + { + using type = remove_cv_ref_t; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + bool RemoveRefs> + struct operand_type + { + using type = expr_ref_t; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + bool RemoveRefs, + bool IsLRef> + struct operand_type + { + using type = remove_cv_ref_t; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + bool IsLRef> + struct operand_type + { + using type = terminal>; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + bool IsLRef> + struct operand_type + { + using type = terminal; + }; + + template class ExprTemplate, typename T> + using operand_type_t = typename operand_type::type; + + + // make_operand + + template + struct make_operand + { + template + auto operator()(U && u) + { + return T{static_cast(u)}; + } + }; + + template class ExprTemplate, typename Tuple> + struct make_operand> + { + auto operator()(ExprTemplate expr) + { + return expr; + } + + template + auto operator()(U && u) + { + return ExprTemplate{ + Tuple{std::addressof(u)}}; + } + }; + + + // free_binary_op_result + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + bool TNonExprUExpr = !is_expr::value && is_expr::value, + bool ULvalueRef = std::is_lvalue_reference::value> + struct free_binary_op_result; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U> + struct free_binary_op_result + { + using lhs_type = operand_type_t; + using rhs_type = expr_ref_t; + using rhs_tuple_type = expr_ref_tuple_t; + using type = ExprTemplate>; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U> + struct free_binary_op_result + { + using lhs_type = operand_type_t; + using rhs_type = remove_cv_ref_t; + using type = ExprTemplate>; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U> + using free_binary_op_result_t = + typename free_binary_op_result::type; + + + // ternary_op_result + + template< + template class ExprTemplate, + typename T, + typename U, + typename V, + bool Valid = + is_expr::value || is_expr::value || is_expr::value> + struct ternary_op_result; + + template< + template class ExprTemplate, + typename T, + typename U, + typename V> + struct ternary_op_result + { + using cond_type = operand_type_t; + using then_type = operand_type_t; + using else_type = operand_type_t; + using type = ExprTemplate< + expr_kind::if_else, + hana::tuple>; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + typename V> + using ternary_op_result_t = + typename ternary_op_result::type; + + + // udt_any_ternary_op_result + + template< + template class ExprTemplate, + typename T, + typename U, + typename V, + template class UdtTrait, + bool Valid = !is_expr::value && !is_expr::value && + !is_expr::value && + (UdtTrait>::value || + UdtTrait>::value || + UdtTrait>::value)> + struct udt_any_ternary_op_result; + + template< + template class ExprTemplate, + typename T, + typename U, + typename V, + template class UdtTrait> + struct udt_any_ternary_op_result + { + using cond_type = operand_type_t; + using then_type = operand_type_t; + using else_type = operand_type_t; + using type = ExprTemplate< + expr_kind::if_else, + hana::tuple>; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + typename V, + template class UdtTrait> + using udt_any_ternary_op_result_t = + typename udt_any_ternary_op_result:: + type; + + + // udt_unary_op_result + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + template class UdtTrait, + bool Valid = !is_expr::value && UdtTrait>::value> + struct udt_unary_op_result; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + template class UdtTrait> + struct udt_unary_op_result + { + using x_type = operand_type_t; + using type = ExprTemplate>; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + template class UdtTrait> + using udt_unary_op_result_t = + typename udt_unary_op_result::type; + + + // udt_udt_binary_op_result + + template class UdtTrait> + struct is_udt_arg + { + static bool const value = + !is_expr::value && UdtTrait>::value; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class TUdtTrait, + template class UUdtTrait, + bool Valid = + is_udt_arg::value && is_udt_arg::value> + struct udt_udt_binary_op_result; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class TUdtTrait, + template class UUdtTrait> + struct udt_udt_binary_op_result< + ExprTemplate, + OpKind, + T, + U, + TUdtTrait, + UUdtTrait, + true> + { + using lhs_type = operand_type_t; + using rhs_type = operand_type_t; + using type = ExprTemplate>; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class TUdtTrait, + template 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 class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class UdtTrait, + bool Valid = !is_expr::value && !is_expr::value && + (UdtTrait>::value || + UdtTrait>::value)> + struct udt_any_binary_op_result; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class UdtTrait> + struct udt_any_binary_op_result + { + using lhs_type = operand_type_t; + using rhs_type = operand_type_t; + using type = ExprTemplate>; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template 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 + struct copy_or_move : std::false_type + { + }; + + template + struct copy_or_move : std::true_type + { + }; + + template + struct copy_or_move : std::true_type + { + }; + + template + struct copy_or_move : std::true_type + { + }; + + + // expr_arity + + enum class expr_arity { invalid, one, two, three, n }; + + template + 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 diff --git a/third-party/boost_1_72_0/boost/yap_1_72_bug/detail/transform.hpp b/third-party/boost_1_72_0/boost/yap_1_72_bug/detail/transform.hpp new file mode 100644 index 0000000..19182d9 --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_1_72_bug/detail/transform.hpp @@ -0,0 +1,590 @@ +// Copyright (C) 2016-2018 T. Zachary Laine +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_YAP_DETAIL_TRANSFORM_HPP_INCLUDED +#define BOOST_YAP_DETAIL_TRANSFORM_HPP_INCLUDED + +#include + +#include + +#include + + +namespace boost { namespace yap { namespace detail { + + template + struct nth_element_impl + { + using type = typename nth_element_impl::type; + }; + + template + struct nth_element_impl<0, T, Ts...> + { + using type = T; + }; + + template + using nth_element = typename nth_element_impl::type; + + template::value> + struct rvalue_ref_to_value; + + template + struct rvalue_ref_to_value + { + using type = typename std::remove_reference::type; + }; + + template + struct rvalue_ref_to_value + { + using type = T; + }; + + template + using rvalue_ref_to_value_t = typename rvalue_ref_to_value::type; + + template + struct rvalue_mover + { + template + constexpr decltype(auto) operator()(T && t) const + { + return static_cast(t); + } + }; + + template<> + struct rvalue_mover + { + template + constexpr std::remove_reference_t operator()(T && t) const + { + return std::move(t); + } + }; + + template + struct placeholder_transform_t + { + using tuple_t = hana::tuple...>; + + placeholder_transform_t(PlaceholderArgs &&... args) : + placeholder_args_(static_cast(args)...) + {} + + template + constexpr decltype(auto) + operator()(expr_tag, boost::yap::placeholder) const + { + static_assert( + I <= decltype(hana::size(std::declval()))::value, + "Out of range placeholder index,"); + using nth_type = nth_element; + return as_expr( + rvalue_mover::value>::value( + placeholder_args_[hana::llong{}])); + } + + tuple_t placeholder_args_; + }; + + template + struct evaluation_transform_t + { + using tuple_t = hana::tuple...>; + + evaluation_transform_t(PlaceholderArgs &&... args) : + placeholder_args_(static_cast(args)...) + {} + + template + constexpr decltype(auto) + operator()(expr_tag, boost::yap::placeholder) const + { + static_assert( + I <= decltype(hana::size(std::declval()))::value, + "Out of range placeholder index,"); + using nth_type = nth_element; + return rvalue_mover::value>{}( + placeholder_args_[hana::llong{}]); + } + + template + constexpr decltype(auto) operator()(expr_tag, T && t) const + { + return static_cast(t); + } + +#define BOOST_YAP_UNARY_OPERATOR_CASE(op, op_name) \ + template \ + constexpr decltype(auto) operator()(expr_tag, T && t) const \ + { \ + return op transform( \ + as_expr(static_cast(t)), *this); \ + } + + BOOST_YAP_UNARY_OPERATOR_CASE(+, unary_plus) + BOOST_YAP_UNARY_OPERATOR_CASE(-, negate) + BOOST_YAP_UNARY_OPERATOR_CASE(*, dereference) + BOOST_YAP_UNARY_OPERATOR_CASE(~, complement) + BOOST_YAP_UNARY_OPERATOR_CASE(&, address_of) + BOOST_YAP_UNARY_OPERATOR_CASE(!, logical_not) + BOOST_YAP_UNARY_OPERATOR_CASE(++, pre_inc) + BOOST_YAP_UNARY_OPERATOR_CASE(--, pre_dec) + + template + constexpr decltype(auto) operator()(expr_tag, T && t) const + { + return transform( + as_expr(static_cast(t)), *this)++; + } + template + constexpr decltype(auto) operator()(expr_tag, T && t) const + { + return transform( + as_expr(static_cast(t)), *this)--; + } + +#undef BOOST_YAP_UNARY_OPERATOR_CASE + +#define BOOST_YAP_BINARY_OPERATOR_CASE(op, op_name) \ + template \ + constexpr decltype(auto) operator()(expr_tag, T && t, U && u) const \ + { \ + return transform(as_expr(static_cast(t)), *this) \ + op transform(as_expr(static_cast(u)), *this); \ + } + + BOOST_YAP_BINARY_OPERATOR_CASE(<<, shift_left) + BOOST_YAP_BINARY_OPERATOR_CASE(>>, shift_right) + BOOST_YAP_BINARY_OPERATOR_CASE(*, multiplies) + BOOST_YAP_BINARY_OPERATOR_CASE(/, divides) + BOOST_YAP_BINARY_OPERATOR_CASE(%, modulus) + BOOST_YAP_BINARY_OPERATOR_CASE(+, plus) + BOOST_YAP_BINARY_OPERATOR_CASE(-, minus) + BOOST_YAP_BINARY_OPERATOR_CASE(<, less) + BOOST_YAP_BINARY_OPERATOR_CASE(>, greater) + BOOST_YAP_BINARY_OPERATOR_CASE(<=, less_equal) + BOOST_YAP_BINARY_OPERATOR_CASE(>=, greater_equal) + BOOST_YAP_BINARY_OPERATOR_CASE(==, equal_to) + BOOST_YAP_BINARY_OPERATOR_CASE(!=, not_equal_to) + BOOST_YAP_BINARY_OPERATOR_CASE(||, logical_or) + BOOST_YAP_BINARY_OPERATOR_CASE(&&, logical_and) + BOOST_YAP_BINARY_OPERATOR_CASE(&, bitwise_and) + BOOST_YAP_BINARY_OPERATOR_CASE(|, bitwise_or) + BOOST_YAP_BINARY_OPERATOR_CASE (^, bitwise_xor) + + // clang-format off +//[ evaluation_transform_comma + template + constexpr decltype(auto) operator()(expr_tag, T && t, U && u) const + { + return transform( + as_expr(static_cast(t)), *this), + transform( + as_expr(static_cast(u)), *this); + } +//] + // clang-format on + + BOOST_YAP_BINARY_OPERATOR_CASE(->*, mem_ptr) + BOOST_YAP_BINARY_OPERATOR_CASE(=, assign) + BOOST_YAP_BINARY_OPERATOR_CASE(<<=, shift_left_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(>>=, shift_right_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(*=, multiplies_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(/=, divides_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(%=, modulus_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(+=, plus_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(-=, minus_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(&=, bitwise_and_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(|=, bitwise_or_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(^=, bitwise_xor_assign) + + template + constexpr decltype(auto) + operator()(expr_tag, T && t, U && u) const + { + return transform( + as_expr(static_cast(t)), *this)[transform( + as_expr(static_cast(u)), *this)]; + } + +#undef BOOST_YAP_BINARY_OPERATOR_CASE + + template + constexpr decltype(auto) + operator()(expr_tag, T && t, U && u, V && v) const + { + return transform(as_expr(static_cast(t)), *this) + ? transform( + as_expr(static_cast(u)), *this) + : transform( + as_expr(static_cast(v)), + *this); + } + + // clang-format off +//[ evaluation_transform_call + template + constexpr decltype(auto) operator()( + expr_tag, Callable && callable, Args &&... args) const + { + return transform(as_expr(static_cast(callable)), *this)( + transform(as_expr(static_cast(args)), *this)... + ); + } +//] + // clang-format on + + tuple_t placeholder_args_; + }; + + + template + struct transform_impl; + + template< + bool Strict, + typename Expr, + typename TransformTuple, + int I, + expr_arity Arity, + typename = void_t<>> + struct transform_expression_tag; + + + // Forward terminals/recurively transform noterminasl; attempted last. + + template + struct default_transform + { + template + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return static_cast(expr); + } + }; + + template + struct default_transform + { + struct incomplete; + + // If you're getting an error because this function is uncallable, + // that's by design. You called yap::transform_strict(expr, xfrom) + // and one or more subexpression of 'expr' are not callable with any + // overload in 'xform'. + template + constexpr incomplete operator()(Expr && expr, TransformTuple transforms) const; + }; + + template< + expr_kind Kind, + template class ExprTemplate, + typename OldTuple, + typename NewTuple> + constexpr auto make_expr_from_tuple( + ExprTemplate const & expr, NewTuple && tuple) + { + return ExprTemplate{std::move(tuple)}; + } + + template + constexpr auto make_expr_from_tuple(Expr const & expr, NewTuple && tuple) + { + return minimal_expr{std::move(tuple)}; + } + + template + constexpr decltype(auto) transform_nonterminal( + Expr const & expr, Tuple && tuple, TransformTuple transforms) + { + auto transformed_tuple = + hana::transform(static_cast(tuple), [&](auto && element) { + using element_t = decltype(element); + auto const kind = remove_cv_ref_t::kind; + ::boost::yap::detail:: + transform_impl + xform; + return xform(static_cast(element), transforms); + }); + auto const kind = remove_cv_ref_t::kind; + return make_expr_from_tuple(expr, std::move(transformed_tuple)); + } + + template<> + struct default_transform + { + template + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return transform_nonterminal(expr, expr.elements, transforms); + } + }; + + template<> + struct default_transform + { + template + decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return transform_nonterminal( + expr, std::move(expr.elements), transforms); + } + }; + + // Dispatch to the next transform, or to the default transform if there is + // no next transform. + + template< + bool Strict, + typename Expr, + typename TransformTuple, + int I, + bool NextTransformExists> + struct next_or_default_transform + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + // Use the next transform. + constexpr expr_kind kind = remove_cv_ref_t::kind; + return detail:: + transform_impl{}( + static_cast(expr), transforms); + } + }; + + template + struct next_or_default_transform + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + // No next transform exists; use the default transform. + constexpr expr_kind kind = remove_cv_ref_t::kind; + return default_transform< + std::is_lvalue_reference::value, + kind == expr_kind::terminal, + Strict>{}(static_cast(expr), transforms); + } + }; + + // Expression-matching; attempted second. + + template< + bool Strict, + typename Expr, + typename TransformTuple, + int I, + typename = detail::void_t<>> + struct transform_expression_expr + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + // No expr-matching succeeded; use the next or default transform. + return next_or_default_transform< + Strict, + Expr, + TransformTuple, + I, + I + 1 < decltype(hana::size( + std::declval()))::value>{}( + static_cast(expr), transforms); + } + }; + + template + struct transform_expression_expr< + Strict, + Expr, + TransformTuple, + I, + void_t()[hana::llong{}])( + std::declval()))>> + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return (*transforms[hana::llong{}])(static_cast(expr)); + } + }; + + + // Tag-matching; attempted first. + + template< + bool Strict, + typename Expr, + typename TransformTuple, + int I, + expr_arity Arity, + typename> + struct transform_expression_tag + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + // No tag-matching succeeded; try expr-matching. + return transform_expression_expr{}( + static_cast(expr), transforms); + } + }; + + template + decltype(auto) terminal_value(T && x) + { + return value_impl(static_cast(x)); + } + + + template + struct transform_expression_tag< + Strict, + Expr, + TransformTuple, + I, + expr_arity::one, + void_t()[hana::llong{}])( + expr_tag::kind>{}, + terminal_value(::boost::yap::value(std::declval()))))>> + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return (*transforms[hana::llong{}])( + expr_tag::kind>{}, + terminal_value( + ::boost::yap::value(static_cast(expr)))); + } + }; + + template + struct transform_expression_tag< + Strict, + Expr, + TransformTuple, + I, + expr_arity::two, + void_t()[hana::llong{}])( + expr_tag::kind>{}, + terminal_value(::boost::yap::left(std::declval())), + terminal_value(::boost::yap::right(std::declval()))))>> + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return (*transforms[hana::llong{}])( + expr_tag::kind>{}, + terminal_value(::boost::yap::left(static_cast(expr))), + terminal_value( + ::boost::yap::right(static_cast(expr)))); + } + }; + + template + struct transform_expression_tag< + Strict, + Expr, + TransformTuple, + I, + expr_arity::three, + void_t()[hana::llong{}])( + expr_tag::kind>{}, + terminal_value(::boost::yap::cond(std::declval())), + terminal_value(::boost::yap::then(std::declval())), + terminal_value(::boost::yap::else_(std::declval()))))>> + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return (*transforms[hana::llong{}])( + expr_tag::kind>{}, + terminal_value(::boost::yap::cond(static_cast(expr))), + terminal_value(::boost::yap::then(static_cast(expr))), + terminal_value( + ::boost::yap::else_(static_cast(expr)))); + } + }; + + template + struct transform_call_unpacker + { + template + constexpr auto operator()( + Expr && expr, + Transform & transform, + std::integer_sequence) const + -> decltype(transform( + expr_tag{}, + terminal_value(::boost::yap::get( + static_cast(expr), hana::llong_c))...)) + { + return transform( + expr_tag{}, + terminal_value(::boost::yap::get( + static_cast(expr), hana::llong_c))...); + } + }; + + template + constexpr auto indices_for(Expr const & expr) + { + constexpr long long size = decltype(hana::size(expr.elements))::value; + return std::make_integer_sequence(); + } + + template + struct transform_expression_tag< + Strict, + Expr, + TransformTuple, + I, + expr_arity::n, + void_t()[hana::llong{}])>{}( + std::declval(), + *std::declval()[hana::llong{}], + indices_for(std::declval())))>> + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + using transform_t = decltype(*transforms[hana::llong{}]); + return transform_call_unpacker{}( + static_cast(expr), + *transforms[hana::llong{}], + indices_for(expr)); + } + }; + + template + struct transform_impl + { + template + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + return detail::transform_expression_tag< + Strict, + Expr, + TransformTuple, + I, + detail::arity_of()>{}( + static_cast(expr), transforms); + } + }; + + template + struct transform_impl + { + template + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return detail::transform_impl{}( + ::boost::yap::deref(static_cast(expr)), transforms); + } + }; + +}}} + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_1_72_bug/expression.hpp b/third-party/boost_1_72_0/boost/yap_1_72_bug/expression.hpp new file mode 100644 index 0000000..84d2936 --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_1_72_bug/expression.hpp @@ -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 + + +namespace boost { namespace yap { + + /** Reference expression template that provides all operator overloads. + + \note Due to a limitation of Doxygen, each of the + value(), left(), right(), and + operator overloads listed here is a stand-in for three member + functions. For each function f, 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 + 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(rhs)) + {} + + tuple_type elements; + + /** A convenience member function that dispatches to the free function + value(). */ + 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 + left(). */ + 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 + right(). */ + 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 value() member + and each of the operator overloads listed here is a stand-in for three + member functions. For each function f, 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 + struct expression> + { + using tuple_type = hana::tuple; + + 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)) {} + + /** Copies \a rhs into the only data mamber, \c elements. */ + constexpr expression(hana::tuple const & rhs) : elements(rhs) {} + + /** Moves \a rhs into the only data mamber, \c elements. */ + constexpr expression(hana::tuple && rhs) : elements(std::move(rhs)) + {} + + tuple_type elements; + + /** A convenience member function that dispatches to the free function + value(). */ + 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 + constexpr auto operator+(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator-(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator*(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator~(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator&(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator!(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator++(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator--(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator++(Expr &&, int); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator--(Expr &&, int); + + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator<<(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator>>(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator*(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator/(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator%(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator+(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator-(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator<(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator>(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator<=(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator>=(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator==(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator!=(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator||(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator&&(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator&(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator|(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator^(LExpr && lhs, RExpr && rhs); + + /** \see BOOST_YAP_USER_EXPR_IF_ELSE for full semantics. */ + template + constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3); + +#endif + + /** Returns make_expression(...). + */ + template + constexpr auto make_expression(T &&... t) + { + return make_expression(static_cast(t)...); + } + + /** Returns make_terminal(t). */ + template + constexpr auto make_terminal(T && t) + { + return make_terminal(static_cast(t)); + } + + /** Returns as_expr(t). */ + template + constexpr decltype(auto) as_expr(T && t) + { + return as_expr(static_cast(t)); + } + +}} + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_1_72_bug/print.hpp b/third-party/boost_1_72_0/boost/yap_1_72_bug/print.hpp new file mode 100644 index 0000000..ca58840 --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_1_72_bug/print.hpp @@ -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 + +#include +#include +#include + + +namespace boost { namespace yap { + + /** Returns the char const * 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 + expr_kind::expr_ref amd expr_kind::terminal, + respectively.*/ + inline 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> + struct printer + { + std::ostream & operator()(std::ostream & os, T const &) + { + return os << "<>"; + } + }; + + template + struct printer< + T, + void_t() << std::declval())>> + { + std::ostream & operator()(std::ostream & os, T const & x) + { + return os << x; + } + }; + + template + inline std::ostream & print_value(std::ostream & os, T const & x) + { + return printer{}(os, x); + } + + template + inline std::ostream & print_value(std::ostream & os, hana::llong) + { + return os << I << "_p"; + } + + template + std::ostream & print_type(std::ostream & os, hana::tuple const &) + { + os << typeindex::type_id().pretty_name(); + if (std::is_const::value) + os << " const"; + if (std::is_volatile::value) + os << " volatile"; + if (std::is_lvalue_reference::value) + os << " &"; + if (std::is_rvalue_reference::value) + os << " &&"; + return os; + } + + template + bool is_const_expr_ref(T const &) + { + return false; + } + template class expr_template> + bool is_const_expr_ref( + expr_template> const &) + { + return true; + } + +#ifdef BOOST_NO_CONSTEXPR_IF + + template + struct print_impl + { + template + 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::kind; + print_impl{}(os, element, indent + 1, indent_str); + }); + + return os; + } + }; + + template<> + struct print_impl + { + template + 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::kind; + print_impl{}( + os, + ::boost::yap::deref(expr), + indent, + indent_str, + true, + ::boost::yap::detail::is_const_expr_ref(expr)); + return os; + } + }; + + template<> + struct print_impl + { + template + 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 + 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 + std::ostream & print(std::ostream & os, Expr const & expr) + { +#ifdef BOOST_NO_CONSTEXPR_IF + return detail::print_impl::kind>{}( + os, expr, 0, " "); +#else + return detail::print_impl(os, expr, 0, " "); +#endif + } + +}} + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_1_72_bug/user_macros.hpp b/third-party/boost_1_72_0/boost/yap_1_72_bug/user_macros.hpp new file mode 100644 index 0000000..6827ba3 --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_1_72_bug/user_macros.hpp @@ -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 +#include +#include +#include + + +#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 const &, + &, and &&. 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 expr_kind, without the + expr_kind:: 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> \ + auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + expr_template const & x) \ + { \ + using lhs_type = ::boost::yap::detail::operand_type_t< \ + result_expr_template, \ + expr_template const &>; \ + using tuple_type = ::boost::hana::tuple; \ + return result_expr_template< \ + ::boost::yap::expr_kind::op_name, \ + tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(x)}}; \ + } \ + template<::boost::yap::expr_kind Kind, typename Tuple> \ + auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + expr_template & x) \ + { \ + using lhs_type = ::boost::yap::detail::operand_type_t< \ + result_expr_template, \ + expr_template &>; \ + using tuple_type = ::boost::hana::tuple; \ + return result_expr_template< \ + ::boost::yap::expr_kind::op_name, \ + tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(x)}}; \ + } \ + template<::boost::yap::expr_kind Kind, typename Tuple> \ + auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + expr_template && x) \ + { \ + using tuple_type = ::boost::hana::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 const + &, &, and &&. For the lvalue reference + overloads, *this is captured by reference into the resulting + expression. For the rvalue reference overload, *this 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 expr_kind, except assign, subscript, or + call, without the expr_kind:: 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 const & lhs, Expr && rhs) \ + { \ + using lhs_type = ::boost::yap::detail::operand_type_t< \ + result_expr_template, \ + expr_template const &>; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return result_expr_template< \ + ::boost::yap::expr_kind::op_name, \ + tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(lhs), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + expr_template & lhs, Expr && rhs) \ + { \ + using lhs_type = ::boost::yap::detail::operand_type_t< \ + result_expr_template, \ + expr_template &>; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return result_expr_template< \ + ::boost::yap::expr_kind::op_name, \ + tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(lhs), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + expr_template && lhs, Expr && rhs) \ + { \ + using lhs_type = ::boost::yap::detail::remove_cv_ref_t< \ + expr_template &&>; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return result_expr_template< \ + ::boost::yap::expr_kind::op_name, \ + tuple_type>{ \ + tuple_type{std::move(lhs), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + T && lhs, expr_template && rhs) \ + ->::boost::yap::detail::free_binary_op_result_t< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template &&> \ + { \ + using result_types = ::boost::yap::detail::free_binary_op_result< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template &&>; \ + using lhs_type = typename result_types::lhs_type; \ + using rhs_type = typename result_types::rhs_type; \ + using tuple_type = ::boost::hana::tuple; \ + return {tuple_type{lhs_type{static_cast(lhs)}, std::move(rhs)}}; \ + } \ + template \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + T && lhs, expr_template const & rhs) \ + ->::boost::yap::detail::free_binary_op_result_t< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template const &> \ + { \ + using result_types = ::boost::yap::detail::free_binary_op_result< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template const &>; \ + using lhs_type = typename result_types::lhs_type; \ + using rhs_type = typename result_types::rhs_type; \ + using tuple_type = ::boost::hana::tuple; \ + using rhs_tuple_type = typename result_types::rhs_tuple_type; \ + return {tuple_type{lhs_type{static_cast(lhs)}, \ + rhs_type{rhs_tuple_type{std::addressof(rhs)}}}}; \ + } \ + template \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + T && lhs, expr_template & rhs) \ + ->::boost::yap::detail::free_binary_op_result_t< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template &> \ + { \ + using result_types = ::boost::yap::detail::free_binary_op_result< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template &>; \ + using lhs_type = typename result_types::lhs_type; \ + using rhs_type = typename result_types::rhs_type; \ + using tuple_type = ::boost::hana::tuple; \ + using rhs_tuple_type = typename result_types::rhs_tuple_type; \ + return {tuple_type{lhs_type{static_cast(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 const &, + &, and &&. For the lvalue reference overloads, + *this is captured by reference into the resulting expression. + For the rvalue reference overload, *this 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::value>> \ + constexpr auto operator=(Expr && rhs) const & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template< \ + typename Expr, \ + typename = std::enable_if_t< \ + !::boost::yap::detail::copy_or_move::value>> \ + constexpr auto operator=(Expr && rhs) & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template< \ + typename Expr, \ + typename = std::enable_if_t< \ + !::boost::yap::detail::copy_or_move::value>> \ + constexpr auto operator=(Expr && rhs) && \ + { \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ + tuple_type{std::move(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(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 const &, + &, and &&. For the lvalue reference overloads, + *this is captured by reference into the resulting expression. + For the rvalue reference overload, *this 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 \ + constexpr auto operator[](Expr && rhs) const & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template \ + constexpr auto operator[](Expr && rhs) & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template \ + constexpr auto operator[](Expr && rhs) && \ + { \ + using lhs_type = \ + ::boost::yap::detail::remove_cv_ref_t; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ + tuple_type{std::move(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(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 const &, &, and + &&. For the lvalue reference overloads, *this + is captured by reference into the resulting expression. For the rvalue + reference overload, *this 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 \ + constexpr auto operator()(U &&... u) const & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using tuple_type = ::boost::hana::tuple< \ + lhs_type, \ + ::boost::yap::detail::operand_type_t...>; \ + return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ + tuple_type{ \ + ::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand< \ + ::boost::yap::detail::operand_type_t>{}( \ + static_cast(u))...}}; \ + } \ + template \ + constexpr auto operator()(U &&... u) & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using tuple_type = ::boost::hana::tuple< \ + lhs_type, \ + ::boost::yap::detail::operand_type_t...>; \ + return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ + tuple_type{ \ + ::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand< \ + ::boost::yap::detail::operand_type_t>{}( \ + static_cast(u))...}}; \ + } \ + template \ + constexpr auto operator()(U &&... u) && \ + { \ + using this_type = \ + ::boost::yap::detail::remove_cv_ref_t; \ + using tuple_type = ::boost::hana::tuple< \ + this_type, \ + ::boost::yap::detail::operand_type_t...>; \ + 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>{}( \ + static_cast(u))...}}; \ + } + + +#ifndef BOOST_YAP_DOXYGEN + +#define BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T(z, n, expr_template) \ + ::boost::yap::detail::operand_type_t +#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))) + +#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 const &, + &, and &&. For the lvalue reference overloads, + *this is captured by reference into the resulting expression. + For the rvalue reference overload, *this 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 \ + constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) const & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + 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{}(*this), \ + BOOST_PP_ENUM( \ + n, \ + BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \ + expr_template)}}; \ + } \ + template \ + constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + 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{}(*this), \ + BOOST_PP_ENUM( \ + n, \ + BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \ + expr_template)}}; \ + } \ + template \ + constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) && \ + { \ + using this_type = \ + ::boost::yap::detail::remove_cv_ref_t; \ + 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 if_else() that acts as an + analogue to the ternary operator (?:), since the ternary + operator is not user-overloadable. The return type of + if_else() is an expression instantiated from the \a + expr_template expression template. + + At least one parameter to if_else() must be an expression. + + For each parameter E passed to if_else(), 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 \ + constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \ + ->::boost::yap::detail:: \ + ternary_op_result_t \ + { \ + using result_types = ::boost::yap::detail:: \ + ternary_op_result; \ + 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; \ + return {tuple_type{::boost::yap::detail::make_operand{}( \ + static_cast(expr1)), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(expr2)), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(expr3))}}; \ + } + + +/** Defines a function if_else() that acts as an analogue to the + ternary operator (?:), since the ternary operator is not + user-overloadable. The return type of if_else() is an + expression instantiated from the \a expr_template expression template. + + Each parameter to if_else() may be any type that is \b not an + expression. At least on parameter must be a type T for which + \code udt_trait>>::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 if_else(). +*/ +#define BOOST_YAP_USER_UDT_ANY_IF_ELSE(expr_template, udt_trait) \ + template \ + 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; \ + return {tuple_type{::boost::yap::detail::make_operand{}( \ + static_cast(expr1)), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(expr2)), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(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>>::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 expr_kind, without the + expr_kind:: 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 \ + 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; \ + return {tuple_type{x_type{static_cast(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>>::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>>::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 expr_kind, without the + expr_kind:: 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 \ + 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; \ + return {tuple_type{ \ + lhs_type{static_cast(lhs)}, \ + rhs_type{static_cast(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>>::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 expr_kind, without the + expr_kind:: 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 \ + 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; \ + return {tuple_type{lhs_type{static_cast(lhs)}, \ + rhs_type{static_cast(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 \ + constexpr auto operator"" _p() \ + { \ + using i = ::boost::hana::llong< \ + ::boost::hana::ic_detail::parse({c...})>; \ + static_assert(1 <= i::value, "Placeholders must be >= 1."); \ + return expr_template< \ + ::boost::yap::expr_kind::terminal, \ + ::boost::hana::tuple<::boost::yap::placeholder>>{}; \ + } + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_1_72_bug/yap.hpp b/third-party/boost_1_72_0/boost/yap_1_72_bug/yap.hpp new file mode 100644 index 0000000..25ef433 --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_1_72_bug/yap.hpp @@ -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 +#include + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_dev/algorithm.hpp b/third-party/boost_1_72_0/boost/yap_dev/algorithm.hpp new file mode 100644 index 0000000..b0d24e1 --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_dev/algorithm.hpp @@ -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 +#include +#include + +#include +#include + + +namespace boost { namespace yap { + +#ifdef BOOST_NO_CONSTEXPR_IF + + namespace detail { + + template + struct deref_impl + { + constexpr decltype(auto) operator()(Expr && expr) + { + return std::move(*expr.elements[hana::llong_c<0>]); + } + }; + + template + struct deref_impl + { + 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 + constexpr decltype(auto) deref(Expr && expr) + { + static_assert( + is_expr::value, "deref() is only defined for expressions."); + + static_assert( + detail::remove_cv_ref_t::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::value && + !std::is_const>::value > + {}(static_cast(expr)); +#else + using namespace hana::literals; + if constexpr ( + std::is_rvalue_reference::value && + !std::is_const>::value) { + return std::move(*expr.elements[0_c]); + } else { + return *expr.elements[0_c]; + } +#endif + } + + namespace detail { + + template + struct lvalue_ref_ith_element + : std::is_lvalue_reference()[hana::llong{}])> + { + }; + +#ifdef BOOST_NO_CONSTEXPR_IF + + template + 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( + ::boost::yap::deref(static_cast(x))); + } + }; + + template + struct value_expr_impl + { + constexpr decltype(auto) operator()(T && x) + { + return x.elements[hana::llong_c<0>]; + } + }; + + template + struct value_expr_impl + { + constexpr decltype(auto) operator()(T && x) + { + return std::move(x.elements[hana::llong_c<0>]); + } + }; + + template + struct value_expr_impl< + T, + false, + ValueOfTerminalsOnly, + false, + IsLvalueRef> + { + constexpr decltype(auto) operator()(T && x) + { + return static_cast(x); + } + }; + + template + struct value_impl_t + { + constexpr decltype(auto) operator()(T && x) + { + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + constexpr detail::expr_arity arity = detail::arity_of(); + 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::value || + detail::lvalue_ref_ith_element< + decltype(x.elements), + 0>::value > {}(static_cast(x)); + } + }; + + template + struct value_impl_t + { + constexpr decltype(auto) operator()(T && x) + { + return static_cast(x); + } + }; + + template + constexpr decltype(auto) value_impl(T && x) + { + return detail:: + value_impl_t::value, ValueOfTerminalsOnly>{}( + static_cast(x)); + } + +#else + + template + constexpr decltype(auto) value_impl(T && x) + { + if constexpr (is_expr::value) { + using namespace hana::literals; + constexpr expr_kind kind = remove_cv_ref_t::kind; + constexpr expr_arity arity = arity_of(); + if constexpr (kind == expr_kind::expr_ref) { + return value_impl( + ::boost::yap::deref(static_cast(x))); + } else if constexpr ( + kind == expr_kind::terminal || + (!ValueOfTerminalsOnly && arity == expr_arity::one)) { + if constexpr ( + std::is_lvalue_reference::value || + detail:: + lvalue_ref_ith_element{}) { + return x.elements[0_c]; + } else { + return std::move(x.elements[0_c]); + } + } else { + return static_cast(x); + } + } else { + return static_cast(x); + } + } + +#endif + } + + /** Forwards the sole element of \a x to the caller, possibly calling + deref() 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 + value(deref(x)). + + - 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 + constexpr decltype(auto) value(T && x) + { + return detail::value_impl(static_cast(x)); + } + +#ifdef BOOST_NO_CONSTEXPR_IF + + template + constexpr decltype(auto) get(Expr && expr, I const & i); + + namespace detail { + + template + struct get_impl; + + template + struct get_impl + { + constexpr decltype(auto) operator()(Expr && expr, hana::llong i) + { + return ::boost::yap::get( + ::boost::yap::deref(static_cast(expr)), i); + } + }; + + template + struct get_impl + { + constexpr decltype(auto) operator()(Expr && expr, hana::llong i) + { + return expr.elements[i]; + } + }; + + template + struct get_impl + { + constexpr decltype(auto) operator()(Expr && expr, hana::llong i) + { + return std::move(expr.elements[i]); + } + }; + } + +#endif + + /** Forwards the i-th element of \a expr to the caller. If \a + expr is a reference expression, the result is get(deref(expr), + i). + + \note get() is only valid if \a Expr is an expression. + */ + template + constexpr decltype(auto) get(Expr && expr, I const & i) + { + static_assert( + is_expr::value, "get() is only defined for expressions."); + static_assert( + hana::IntegralConstant::value, + "'i' must be an IntegralConstant"); + + constexpr expr_kind kind = detail::remove_cv_ref_t::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::value>{}(static_cast(expr), i); +#else + using namespace hana::literals; + if constexpr (kind == expr_kind::expr_ref) { + return ::boost::yap::get( + ::boost::yap::deref(static_cast(expr)), i); + } else { + if constexpr (std::is_lvalue_reference::value) { + return expr.elements[i]; + } else { + return std::move(expr.elements[i]); + } + } +#endif + } + + /** Returns get(expr, boost::hana::llong_c). */ + template + constexpr decltype(auto) get_c(Expr && expr) + { + return ::boost::yap::get(static_cast(expr), hana::llong_c); + } + + /** Returns the left operand in a binary operator expression. + + Equivalent to get(expr, 0_c). + + \note left() is only valid if \a Expr is a binary + operator expression. + */ + template + constexpr decltype(auto) left(Expr && expr) + { + using namespace hana::literals; + return ::boost::yap::get(static_cast(expr), 0_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + static_assert( + kind == expr_kind::expr_ref || + detail::arity_of() == detail::expr_arity::two, + "left() is only defined for binary expressions."); + } + + /** Returns the right operand in a binary operator expression. + + Equivalent to get(expr, 1_c). + + \note right() is only valid if \a Expr is a binary + operator expression. + */ + template + constexpr decltype(auto) right(Expr && expr) + { + using namespace hana::literals; + return ::boost::yap::get(static_cast(expr), 1_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + static_assert( + kind == expr_kind::expr_ref || + detail::arity_of() == detail::expr_arity::two, + "right() is only defined for binary expressions."); + } + + /** Returns the condition expression in an if_else expression. + + Equivalent to get(expr, 0_c). + + \note cond() is only valid if \a Expr is an + expr_kind::if_else expression. + */ + template + constexpr decltype(auto) cond(Expr && expr) + { + using namespace hana::literals; + return ::boost::yap::get(static_cast(expr), 0_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::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 get(expr, 1_c). + + \note then() is only valid if \a Expr is an + expr_kind::if_else expression. + */ + template + constexpr decltype(auto) then(Expr && expr) + { + using namespace hana::literals; + return ::boost::yap::get(static_cast(expr), 1_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::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 get(expr, 2_c). + + \note else_() is only valid if \a Expr is an + expr_kind::if_else expression. + */ + template + constexpr decltype(auto) else_(Expr && expr) + { + using namespace hana::literals; + return ::boost::yap::get(static_cast(expr), 2_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::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 get(expr, 0). + + \note callable() is only valid if \a Expr is an + expr_kind::call expression. + */ + template + constexpr decltype(auto) callable(Expr && expr) + { + return ::boost::yap::get(static_cast(expr), hana::llong_c<0>); + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + static_assert( + kind == expr_kind::expr_ref || + detail::arity_of() == detail::expr_arity::n, + "callable() is only defined for call expressions."); + } + + /** Returns the i-th argument expression in a call expression. + + Equivalent to get(expr, i + 1). + + \note argument() is only valid if \a Expr is an + expr_kind::call expression. + */ + template + constexpr decltype(auto) argument(Expr && expr, hana::llong i) + { + return ::boost::yap::get( + static_cast(expr), hana::llong_c); + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + static_assert( + kind == expr_kind::expr_ref || + detail::arity_of() == 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 make_expression() is only valid if the number of + parameters passed is appropriate for \a Kind. + */ + template< + template class ExprTemplate, + expr_kind Kind, + typename... T> + constexpr auto make_expression(T &&... t) + { + constexpr detail::expr_arity arity = detail::arity_of(); + 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...>; + return ExprTemplate{tuple_type{ + detail::make_operand>{}( + static_cast(t))...}}; + } + + /** Makes a new terminal expression instantiated from the expression + template \a ExprTemplate, with the given value as its sole element. + + \note make_terminal() is only valid if \a T is \b not + an expression. + */ + template class ExprTemplate, typename T> + constexpr auto make_terminal(T && t) + { + static_assert( + !is_expr::value, + "make_terminal() is only defined for non expressions."); + using result_type = detail::operand_type_t; + using tuple_type = decltype(std::declval().elements); + return result_type{tuple_type{static_cast(t)}}; + } + +#ifdef BOOST_NO_CONSTEXPR_IF + + namespace detail { + + template< + template class ExprTemplate, + typename T, + bool IsExpr> + struct as_expr_impl + { + constexpr decltype(auto) operator()(T && t) + { + return static_cast(t); + } + }; + + template class ExprTemplate, typename T> + struct as_expr_impl + { + constexpr decltype(auto) operator()(T && t) + { + return make_terminal(static_cast(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 class ExprTemplate, typename T> + constexpr decltype(auto) as_expr(T && t) + { +#ifdef BOOST_NO_CONSTEXPR_IF + return detail::as_expr_impl::value>{}( + static_cast(t)); +#else + if constexpr (is_expr::value) { + return static_cast(t); + } else { + return make_terminal(static_cast(t)); + } +#endif + } + + /** A callable type that evaluates its contained expression when called. + + \see make_expression_function() + */ + template + struct expression_function + { + template + constexpr decltype(auto) operator()(U &&... u) + { + return ::boost::yap::evaluate(expr, static_cast(u)...); + } + + Expr expr; + }; + + namespace detail { + + template + 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 make_expression_function() is only valid if \a + Expr is an expression. + */ + template + constexpr auto make_expression_function(Expr && expr) + { + static_assert( + is_expr::value, + "make_expression_function() is only defined for expressions."); + using stored_type = + detail::operand_type_t; + return expression_function{ + detail::make_operand{}(static_cast(expr))}; + } +}} + +#include + +namespace boost { namespace yap { + + /** Returns a transform object that replaces placeholders within an + expression with the given values. + */ + template + constexpr auto replacements(T &&... t) + { + return detail::placeholder_transform_t(static_cast(t)...); + } + + /** Returns \a expr with the placeholders replaced by YAP terminals + containing the given values. + + \note replace_placeholders(expr, t...) is only valid if + \a expr is an expression, and max_p <= sizeof...(t), + where max_p is the maximum placeholder index in \a expr. + */ + template + constexpr decltype(auto) replace_placeholders(Expr && expr, T &&... t) + { + static_assert( + is_expr::value, + "evaluate() is only defined for expressions."); + return transform( + static_cast(expr), replacements(static_cast(t)...)); + } + + /** Returns a transform object that evaluates an expression using the + built-in semantics. The transform replaces any placeholders with the + given values. + */ + template + constexpr auto evaluation(T &&... t) + { + return detail::evaluation_transform_t(static_cast(t)...); + } + + /** Evaluates \a expr using the built-in semantics, replacing any + placeholders with the given values. + + \note evaluate(expr) is only valid if \a expr is an + expression. + */ + template + constexpr decltype(auto) evaluate(Expr && expr, T &&... t) + { + static_assert( + is_expr::value, + "evaluate() is only defined for expressions."); + return transform( + static_cast(expr), evaluation(static_cast(t)...)); + } + + namespace detail { + + template + constexpr auto make_transform_tuple(Transforms &... transforms) + { + return hana::tuple{&transforms...}; + } + + template + struct transform_ + { + template + 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::kind; + return detail:: + transform_impl{}( + static_cast(expr), transform_tuple); + } + }; + } + + /** Returns the result of transforming (all or part of) \a expr using + whatever overloads of Transform::operator() 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 + constexpr decltype(auto) + transform(Expr && expr, Transform && transform, Transforms &&... transforms) + { + static_assert( + is_expr::value, + "transform() is only defined for expressions."); + return detail::transform_{}( + static_cast(expr), transform, transforms...); + } + + /** Returns the result of transforming \a expr using whichever overload of + Transform::operator() best matches \a expr. If no + overload of Transform::operator() 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 + constexpr decltype(auto) transform_strict( + Expr && expr, Transform && transform, Transforms &&... transforms) + { + static_assert( + is_expr::value, + "transform() is only defined for expressions."); + return detail::transform_{}( + static_cast(expr), transform, transforms...); + } + +}} + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_dev/algorithm_fwd.hpp b/third-party/boost_1_72_0/boost/yap_dev/algorithm_fwd.hpp new file mode 100644 index 0000000..c3b437d --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_dev/algorithm_fwd.hpp @@ -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 + +#include +#include +#include + + +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 + struct placeholder : hana::llong + { + }; + +#ifdef BOOST_YAP_DOXYGEN + + /** A metafunction that evaluates to std::true_type if \a Expr is an + Expression, and std::false_type otherwise. */ + template + struct is_expr; + +#else + + template + struct expression; + + namespace detail { + + // void_t + + template + using void_t = void; + + // remove_cv_ref + + template + struct remove_cv_ref : std::remove_cv> + { + }; + + template + using remove_cv_ref_t = typename remove_cv_ref::type; + } + + template< + typename Expr, + typename = detail::void_t<>, + typename = detail::void_t<>> + struct is_expr : std::false_type + { + }; + + template + struct is_expr< + Expr, + detail::void_t::kind)>, + detail::void_t().elements)>> + : std::integral_constant< + bool, + std::is_same< + std::remove_cv_t::kind)>, + expr_kind>::value && + hana::is_a< + hana::tuple_tag, + decltype(std::declval().elements)>> + { + }; + +#endif // BOOST_YAP_DOXYGEN + + /** A convenience alias for a terminal expression holding a \a T, + instantiated from expression template \a expr_template. */ + template class expr_template, typename T> + using terminal = expr_template>; + + /** A convenience alias for a reference expression holding an expression + \a T, instantiated from expression template \a expr_template. */ + template class expr_template, typename T> + using expression_ref = expr_template< + expr_kind::expr_ref, + hana::tuple *>>; + +#ifndef BOOST_YAP_DOXYGEN + + template + constexpr decltype(auto) evaluate(Expr && expr, T &&... t); + + template + constexpr decltype(auto) transform( + Expr && expr, Transform && transform, Transforms &&... transforms); + + template + constexpr decltype(auto) transform_strict( + Expr && expr, Transform && transform, Transforms &&... transforms); + + template + constexpr decltype(auto) deref(T && x); + + template + constexpr decltype(auto) value(Expr && expr); + +#endif // BOOST_YAP_DOXYGEN + + namespace literals { + + /** Creates literal placeholders. Placeholder indices are 1-based. */ + template + constexpr auto operator"" _p() + { + using i = hana::llong({c...})>; + static_assert(1 <= i::value, "Placeholders must be >= 1."); + return expression< + expr_kind::terminal, + hana::tuple>>{}; + } + } + + /** Used as the tag-type passed to a transform function written in the + tag-transform form. */ + template + 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 + struct minimal_expr + { + static expr_kind const kind = Kind; + Tuple elements; + }; + +}} + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_dev/config.hpp b/third-party/boost_1_72_0/boost/yap_dev/config.hpp new file mode 100644 index 0000000..ec067de --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_dev/config.hpp @@ -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 diff --git a/third-party/boost_1_72_0/boost/yap_dev/detail/algorithm.hpp b/third-party/boost_1_72_0/boost/yap_dev/detail/algorithm.hpp new file mode 100644 index 0000000..54e71e0 --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_dev/detail/algorithm.hpp @@ -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 + +#include +#include + +#include +#include + + +namespace boost { namespace yap { namespace detail { + + // static_const + + template + struct static_const + { + static constexpr T value{}; + }; + + template + constexpr T static_const::value; + + + // partial_decay + + template + struct partial_decay + { + using type = T; + }; + + template + struct partial_decay + { + using type = T *; + }; + template + struct partial_decay + { + using type = T *; + }; + + template + struct partial_decay + { + using type = T *; + }; + template + struct partial_decay + { + using type = T *; + }; + + template + struct partial_decay + { + using type = R (*)(A...); + }; + template + struct partial_decay + { + using type = R (*)(A..., ...); + }; + + template + struct partial_decay + { + using type = R (*)(A...); + }; + template + struct partial_decay + { + using type = R (*)(A..., ...); + }; + + template + struct partial_decay + { + using type = R (*)(A...); + }; + template + struct partial_decay + { + using type = R (*)(A..., ...); + }; + + + // operand_value_type_phase_1 + + template< + typename T, + typename U = typename detail::partial_decay::type, + bool AddRValueRef = std::is_same::value && !std::is_const::value> + struct operand_value_type_phase_1; + + template + struct operand_value_type_phase_1 + { + using type = U &&; + }; + + template + struct operand_value_type_phase_1 + { + using type = U; + }; + + + // expr_ref + + template class ExprTemplate, typename T> + struct expr_ref + { + using type = expression_ref; + }; + + template class ExprTemplate, typename Tuple> + struct expr_ref &> + { + using type = ExprTemplate; + }; + + template class ExprTemplate, typename Tuple> + struct expr_ref< + ExprTemplate, + ExprTemplate const &> + { + using type = ExprTemplate; + }; + + template class ExprTemplate, typename T> + using expr_ref_t = typename expr_ref::type; + + template class ExprTemplate, typename T> + struct expr_ref_tuple; + + template class ExprTemplate, typename Tuple> + struct expr_ref_tuple< + ExprTemplate, + ExprTemplate> + { + using type = Tuple; + }; + + template class ExprTemplate, typename T> + using expr_ref_tuple_t = typename expr_ref_tuple::type; + + + // operand_type + + template< + template class ExprTemplate, + typename T, + typename U = typename operand_value_type_phase_1::type, + bool RemoveRefs = std::is_rvalue_reference::value, + bool IsExpr = is_expr::value, + bool IsLRef = std::is_lvalue_reference::value> + struct operand_type; + + template< + template class ExprTemplate, + typename T, + typename U, + bool RemoveRefs> + struct operand_type + { + using type = remove_cv_ref_t; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + bool RemoveRefs> + struct operand_type + { + using type = expr_ref_t; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + bool RemoveRefs, + bool IsLRef> + struct operand_type + { + using type = remove_cv_ref_t; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + bool IsLRef> + struct operand_type + { + using type = terminal>; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + bool IsLRef> + struct operand_type + { + using type = terminal; + }; + + template class ExprTemplate, typename T> + using operand_type_t = typename operand_type::type; + + + // make_operand + + template + struct make_operand + { + template + constexpr auto operator()(U && u) + { + return T{static_cast(u)}; + } + }; + + template class ExprTemplate, typename Tuple> + struct make_operand> + { + constexpr auto operator()(ExprTemplate expr) + { + return expr; + } + + template + constexpr auto operator()(U && u) + { + return ExprTemplate{ + Tuple{std::addressof(u)}}; + } + }; + + + // free_binary_op_result + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + bool TNonExprUExpr = !is_expr::value && is_expr::value, + bool ULvalueRef = std::is_lvalue_reference::value> + struct free_binary_op_result; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U> + struct free_binary_op_result + { + using lhs_type = operand_type_t; + using rhs_type = expr_ref_t; + using rhs_tuple_type = expr_ref_tuple_t; + using type = ExprTemplate>; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U> + struct free_binary_op_result + { + using lhs_type = operand_type_t; + using rhs_type = remove_cv_ref_t; + using type = ExprTemplate>; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U> + using free_binary_op_result_t = + typename free_binary_op_result::type; + + + // ternary_op_result + + template< + template class ExprTemplate, + typename T, + typename U, + typename V, + bool Valid = + is_expr::value || is_expr::value || is_expr::value> + struct ternary_op_result; + + template< + template class ExprTemplate, + typename T, + typename U, + typename V> + struct ternary_op_result + { + using cond_type = operand_type_t; + using then_type = operand_type_t; + using else_type = operand_type_t; + using type = ExprTemplate< + expr_kind::if_else, + hana::tuple>; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + typename V> + using ternary_op_result_t = + typename ternary_op_result::type; + + + // udt_any_ternary_op_result + + template< + template class ExprTemplate, + typename T, + typename U, + typename V, + template class UdtTrait, + bool Valid = !is_expr::value && !is_expr::value && + !is_expr::value && + (UdtTrait>::value || + UdtTrait>::value || + UdtTrait>::value)> + struct udt_any_ternary_op_result; + + template< + template class ExprTemplate, + typename T, + typename U, + typename V, + template class UdtTrait> + struct udt_any_ternary_op_result + { + using cond_type = operand_type_t; + using then_type = operand_type_t; + using else_type = operand_type_t; + using type = ExprTemplate< + expr_kind::if_else, + hana::tuple>; + }; + + template< + template class ExprTemplate, + typename T, + typename U, + typename V, + template class UdtTrait> + using udt_any_ternary_op_result_t = + typename udt_any_ternary_op_result:: + type; + + + // udt_unary_op_result + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + template class UdtTrait, + bool Valid = !is_expr::value && UdtTrait>::value> + struct udt_unary_op_result; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + template class UdtTrait> + struct udt_unary_op_result + { + using x_type = operand_type_t; + using type = ExprTemplate>; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + template class UdtTrait> + using udt_unary_op_result_t = + typename udt_unary_op_result::type; + + + // udt_udt_binary_op_result + + template class UdtTrait> + struct is_udt_arg + { + static bool const value = + !is_expr::value && UdtTrait>::value; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class TUdtTrait, + template class UUdtTrait, + bool Valid = + is_udt_arg::value && is_udt_arg::value> + struct udt_udt_binary_op_result; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class TUdtTrait, + template class UUdtTrait> + struct udt_udt_binary_op_result< + ExprTemplate, + OpKind, + T, + U, + TUdtTrait, + UUdtTrait, + true> + { + using lhs_type = operand_type_t; + using rhs_type = operand_type_t; + using type = ExprTemplate>; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class TUdtTrait, + template 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 class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class UdtTrait, + bool Valid = !is_expr::value && !is_expr::value && + (UdtTrait>::value || + UdtTrait>::value)> + struct udt_any_binary_op_result; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template class UdtTrait> + struct udt_any_binary_op_result + { + using lhs_type = operand_type_t; + using rhs_type = operand_type_t; + using type = ExprTemplate>; + }; + + template< + template class ExprTemplate, + expr_kind OpKind, + typename T, + typename U, + template 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 + struct copy_or_move : std::false_type + { + }; + + template + struct copy_or_move : std::true_type + { + }; + + template + struct copy_or_move : std::true_type + { + }; + + template + struct copy_or_move : std::true_type + { + }; + + + // expr_arity + + enum class expr_arity { invalid, one, two, three, n }; + + template + 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 diff --git a/third-party/boost_1_72_0/boost/yap_dev/detail/transform.hpp b/third-party/boost_1_72_0/boost/yap_dev/detail/transform.hpp new file mode 100644 index 0000000..1d5949e --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_dev/detail/transform.hpp @@ -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 + +#include + +#include + + +namespace boost { namespace yap { namespace detail { + + template + struct nth_element_impl + { + using type = typename nth_element_impl::type; + }; + + template + struct nth_element_impl<0, T, Ts...> + { + using type = T; + }; + + template + using nth_element = typename nth_element_impl::type; + + template::value> + struct rvalue_ref_to_value; + + template + struct rvalue_ref_to_value + { + using type = typename std::remove_reference::type; + }; + + template + struct rvalue_ref_to_value + { + using type = T; + }; + + template + using rvalue_ref_to_value_t = typename rvalue_ref_to_value::type; + + template + struct rvalue_mover + { + template + constexpr decltype(auto) operator()(T && t) const + { + return static_cast(t); + } + }; + + template<> + struct rvalue_mover + { + template + constexpr std::remove_reference_t operator()(T && t) const + { + return std::move(t); + } + }; + + template + struct placeholder_transform_t + { + using tuple_t = hana::tuple...>; + + constexpr placeholder_transform_t(PlaceholderArgs &&... args) : + placeholder_args_(static_cast(args)...) + {} + + template + constexpr decltype(auto) + operator()(expr_tag, boost::yap::placeholder) const + { + static_assert( + I <= decltype(hana::size(std::declval()))::value, + "Out of range placeholder index,"); + using nth_type = nth_element; + return as_expr( + rvalue_mover::value>{}( + placeholder_args_[hana::llong{}])); + } + + tuple_t placeholder_args_; + }; + + template + struct evaluation_transform_t + { + using tuple_t = hana::tuple...>; + + constexpr evaluation_transform_t(PlaceholderArgs &&... args) : + placeholder_args_(static_cast(args)...) + {} + + template + constexpr decltype(auto) + operator()(expr_tag, boost::yap::placeholder) const + { + static_assert( + I <= decltype(hana::size(std::declval()))::value, + "Out of range placeholder index,"); + using nth_type = nth_element; + return rvalue_mover::value>{}( + placeholder_args_[hana::llong{}]); + } + + template + constexpr decltype(auto) operator()(expr_tag, T && t) const + { + return static_cast(t); + } + +#define BOOST_YAP_UNARY_OPERATOR_CASE(op, op_name) \ + template \ + constexpr decltype(auto) operator()(expr_tag, T && t) const \ + { \ + return op transform( \ + as_expr(static_cast(t)), *this); \ + } + + BOOST_YAP_UNARY_OPERATOR_CASE(+, unary_plus) + BOOST_YAP_UNARY_OPERATOR_CASE(-, negate) + BOOST_YAP_UNARY_OPERATOR_CASE(*, dereference) + BOOST_YAP_UNARY_OPERATOR_CASE(~, complement) + BOOST_YAP_UNARY_OPERATOR_CASE(&, address_of) + BOOST_YAP_UNARY_OPERATOR_CASE(!, logical_not) + BOOST_YAP_UNARY_OPERATOR_CASE(++, pre_inc) + BOOST_YAP_UNARY_OPERATOR_CASE(--, pre_dec) + + template + constexpr decltype(auto) operator()(expr_tag, T && t) const + { + return transform( + as_expr(static_cast(t)), *this)++; + } + template + constexpr decltype(auto) operator()(expr_tag, T && t) const + { + return transform( + as_expr(static_cast(t)), *this)--; + } + +#undef BOOST_YAP_UNARY_OPERATOR_CASE + +#define BOOST_YAP_BINARY_OPERATOR_CASE(op, op_name) \ + template \ + constexpr decltype(auto) operator()(expr_tag, T && t, U && u) const \ + { \ + return transform(as_expr(static_cast(t)), *this) \ + op transform(as_expr(static_cast(u)), *this); \ + } + + BOOST_YAP_BINARY_OPERATOR_CASE(<<, shift_left) + BOOST_YAP_BINARY_OPERATOR_CASE(>>, shift_right) + BOOST_YAP_BINARY_OPERATOR_CASE(*, multiplies) + BOOST_YAP_BINARY_OPERATOR_CASE(/, divides) + BOOST_YAP_BINARY_OPERATOR_CASE(%, modulus) + BOOST_YAP_BINARY_OPERATOR_CASE(+, plus) + BOOST_YAP_BINARY_OPERATOR_CASE(-, minus) + BOOST_YAP_BINARY_OPERATOR_CASE(<, less) + BOOST_YAP_BINARY_OPERATOR_CASE(>, greater) + BOOST_YAP_BINARY_OPERATOR_CASE(<=, less_equal) + BOOST_YAP_BINARY_OPERATOR_CASE(>=, greater_equal) + BOOST_YAP_BINARY_OPERATOR_CASE(==, equal_to) + BOOST_YAP_BINARY_OPERATOR_CASE(!=, not_equal_to) + BOOST_YAP_BINARY_OPERATOR_CASE(||, logical_or) + BOOST_YAP_BINARY_OPERATOR_CASE(&&, logical_and) + BOOST_YAP_BINARY_OPERATOR_CASE(&, bitwise_and) + BOOST_YAP_BINARY_OPERATOR_CASE(|, bitwise_or) + BOOST_YAP_BINARY_OPERATOR_CASE (^, bitwise_xor) + + // clang-format off +//[ evaluation_transform_comma + template + constexpr decltype(auto) operator()(expr_tag, T && t, U && u) const + { + return transform( + as_expr(static_cast(t)), *this), + transform( + as_expr(static_cast(u)), *this); + } +//] + // clang-format on + + BOOST_YAP_BINARY_OPERATOR_CASE(->*, mem_ptr) + BOOST_YAP_BINARY_OPERATOR_CASE(=, assign) + BOOST_YAP_BINARY_OPERATOR_CASE(<<=, shift_left_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(>>=, shift_right_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(*=, multiplies_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(/=, divides_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(%=, modulus_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(+=, plus_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(-=, minus_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(&=, bitwise_and_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(|=, bitwise_or_assign) + BOOST_YAP_BINARY_OPERATOR_CASE(^=, bitwise_xor_assign) + + template + constexpr decltype(auto) + operator()(expr_tag, T && t, U && u) const + { + return transform( + as_expr(static_cast(t)), *this)[transform( + as_expr(static_cast(u)), *this)]; + } + +#undef BOOST_YAP_BINARY_OPERATOR_CASE + + template + constexpr decltype(auto) + operator()(expr_tag, T && t, U && u, V && v) const + { + return transform(as_expr(static_cast(t)), *this) + ? transform( + as_expr(static_cast(u)), *this) + : transform( + as_expr(static_cast(v)), + *this); + } + + // clang-format off +//[ evaluation_transform_call + template + constexpr decltype(auto) operator()( + expr_tag, Callable && callable, Args &&... args) const + { + return transform(as_expr(static_cast(callable)), *this)( + transform(as_expr(static_cast(args)), *this)... + ); + } +//] + // clang-format on + + tuple_t placeholder_args_; + }; + + + template + struct transform_impl; + + template< + bool Strict, + typename Expr, + typename TransformTuple, + int I, + expr_arity Arity, + typename = void_t<>> + struct transform_expression_tag; + + + // Forward terminals/recurively transform noterminasl; attempted last. + + template + struct default_transform + { + template + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return static_cast(expr); + } + }; + + template + struct default_transform + { + struct incomplete; + + // If you're getting an error because this function is uncallable, + // that's by design. You called yap::transform_strict(expr, xfrom) + // and one or more subexpression of 'expr' are not callable with any + // overload in 'xform'. + template + constexpr incomplete operator()(Expr && expr, TransformTuple transforms) const; + }; + + template< + expr_kind Kind, + template class ExprTemplate, + typename OldTuple, + typename NewTuple> + constexpr auto make_expr_from_tuple( + ExprTemplate const & expr, NewTuple && tuple) + { + return ExprTemplate{std::move(tuple)}; + } + + template + constexpr auto make_expr_from_tuple(Expr const & expr, NewTuple && tuple) + { + return minimal_expr{std::move(tuple)}; + } + + template + constexpr decltype(auto) transform_nonterminal( + Expr const & expr, Tuple && tuple, TransformTuple transforms) + { + auto transformed_tuple = + hana::transform(static_cast(tuple), [&](auto && element) { + using element_t = decltype(element); + auto const kind = remove_cv_ref_t::kind; + ::boost::yap::detail:: + transform_impl + xform; + return xform(static_cast(element), transforms); + }); + auto const kind = remove_cv_ref_t::kind; + return make_expr_from_tuple(expr, std::move(transformed_tuple)); + } + + template<> + struct default_transform + { + template + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return transform_nonterminal(expr, expr.elements, transforms); + } + }; + + template<> + struct default_transform + { + template + constexpr decltype(auto) + operator()(Expr && expr, TransformTuple transforms) const + { + return transform_nonterminal( + expr, std::move(expr.elements), transforms); + } + }; + + // Dispatch to the next transform, or to the default transform if there is + // no next transform. + + template< + bool Strict, + typename Expr, + typename TransformTuple, + int I, + bool NextTransformExists> + struct next_or_default_transform + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + // Use the next transform. + constexpr expr_kind kind = remove_cv_ref_t::kind; + return detail:: + transform_impl{}( + static_cast(expr), transforms); + } + }; + + template + struct next_or_default_transform + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + // No next transform exists; use the default transform. + constexpr expr_kind kind = remove_cv_ref_t::kind; + return default_transform< + std::is_lvalue_reference::value, + kind == expr_kind::terminal, + Strict>{}(static_cast(expr), transforms); + } + }; + + // Expression-matching; attempted second. + + template< + bool Strict, + typename Expr, + typename TransformTuple, + int I, + typename = detail::void_t<>> + struct transform_expression_expr + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + // No expr-matching succeeded; use the next or default transform. + return next_or_default_transform< + Strict, + Expr, + TransformTuple, + I, + I + 1 < decltype(hana::size( + std::declval()))::value>{}( + static_cast(expr), transforms); + } + }; + + template + struct transform_expression_expr< + Strict, + Expr, + TransformTuple, + I, + void_t()[hana::llong{}])( + std::declval()))>> + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return (*transforms[hana::llong{}])(static_cast(expr)); + } + }; + + + // Tag-matching; attempted first. + + template< + bool Strict, + typename Expr, + typename TransformTuple, + int I, + expr_arity Arity, + typename> + struct transform_expression_tag + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + // No tag-matching succeeded; try expr-matching. + return transform_expression_expr{}( + static_cast(expr), transforms); + } + }; + + template + constexpr decltype(auto) terminal_value(T && x) + { + return value_impl(static_cast(x)); + } + + + template + struct transform_expression_tag< + Strict, + Expr, + TransformTuple, + I, + expr_arity::one, + void_t()[hana::llong{}])( + expr_tag::kind>{}, + terminal_value(::boost::yap::value(std::declval()))))>> + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return (*transforms[hana::llong{}])( + expr_tag::kind>{}, + terminal_value( + ::boost::yap::value(static_cast(expr)))); + } + }; + + template + struct transform_expression_tag< + Strict, + Expr, + TransformTuple, + I, + expr_arity::two, + void_t()[hana::llong{}])( + expr_tag::kind>{}, + terminal_value(::boost::yap::left(std::declval())), + terminal_value(::boost::yap::right(std::declval()))))>> + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return (*transforms[hana::llong{}])( + expr_tag::kind>{}, + terminal_value(::boost::yap::left(static_cast(expr))), + terminal_value( + ::boost::yap::right(static_cast(expr)))); + } + }; + + template + struct transform_expression_tag< + Strict, + Expr, + TransformTuple, + I, + expr_arity::three, + void_t()[hana::llong{}])( + expr_tag::kind>{}, + terminal_value(::boost::yap::cond(std::declval())), + terminal_value(::boost::yap::then(std::declval())), + terminal_value(::boost::yap::else_(std::declval()))))>> + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return (*transforms[hana::llong{}])( + expr_tag::kind>{}, + terminal_value(::boost::yap::cond(static_cast(expr))), + terminal_value(::boost::yap::then(static_cast(expr))), + terminal_value( + ::boost::yap::else_(static_cast(expr)))); + } + }; + + template + struct transform_call_unpacker + { + template + constexpr auto operator()( + Expr && expr, + Transform & transform, + std::integer_sequence) const + -> decltype(transform( + expr_tag{}, + terminal_value(::boost::yap::get( + static_cast(expr), hana::llong_c))...)) + { + return transform( + expr_tag{}, + terminal_value(::boost::yap::get( + static_cast(expr), hana::llong_c))...); + } + }; + + template + constexpr auto indices_for(Expr const & expr) + { + constexpr long long size = decltype(hana::size(expr.elements))::value; + return std::make_integer_sequence(); + } + + template + struct transform_expression_tag< + Strict, + Expr, + TransformTuple, + I, + expr_arity::n, + void_t()[hana::llong{}])>{}( + std::declval(), + *std::declval()[hana::llong{}], + indices_for(std::declval())))>> + { + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + using transform_t = decltype(*transforms[hana::llong{}]); + return transform_call_unpacker{}( + static_cast(expr), + *transforms[hana::llong{}], + indices_for(expr)); + } + }; + + template + struct transform_impl + { + template + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + constexpr expr_kind kind = detail::remove_cv_ref_t::kind; + return detail::transform_expression_tag< + Strict, + Expr, + TransformTuple, + I, + detail::arity_of()>{}( + static_cast(expr), transforms); + } + }; + + template + struct transform_impl + { + template + constexpr decltype(auto) operator()(Expr && expr, TransformTuple transforms) const + { + return detail::transform_impl{}( + ::boost::yap::deref(static_cast(expr)), transforms); + } + }; + +}}} + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_dev/expression.hpp b/third-party/boost_1_72_0/boost/yap_dev/expression.hpp new file mode 100644 index 0000000..84d2936 --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_dev/expression.hpp @@ -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 + + +namespace boost { namespace yap { + + /** Reference expression template that provides all operator overloads. + + \note Due to a limitation of Doxygen, each of the + value(), left(), right(), and + operator overloads listed here is a stand-in for three member + functions. For each function f, 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 + 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(rhs)) + {} + + tuple_type elements; + + /** A convenience member function that dispatches to the free function + value(). */ + 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 + left(). */ + 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 + right(). */ + 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 value() member + and each of the operator overloads listed here is a stand-in for three + member functions. For each function f, 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 + struct expression> + { + using tuple_type = hana::tuple; + + 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)) {} + + /** Copies \a rhs into the only data mamber, \c elements. */ + constexpr expression(hana::tuple const & rhs) : elements(rhs) {} + + /** Moves \a rhs into the only data mamber, \c elements. */ + constexpr expression(hana::tuple && rhs) : elements(std::move(rhs)) + {} + + tuple_type elements; + + /** A convenience member function that dispatches to the free function + value(). */ + 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 + constexpr auto operator+(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator-(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator*(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator~(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator&(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator!(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator++(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator--(Expr &&); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator++(Expr &&, int); + /** \see BOOST_YAP_USER_UNARY_OPERATOR for full semantics. */ + template + constexpr auto operator--(Expr &&, int); + + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator<<(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator>>(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator*(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator/(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator%(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator+(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator-(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator<(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator>(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator<=(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator>=(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator==(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator!=(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator||(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator&&(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator&(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator|(LExpr && lhs, RExpr && rhs); + /** \see BOOST_YAP_USER_BINARY_OPERATOR for full semantics. */ + template + constexpr auto operator^(LExpr && lhs, RExpr && rhs); + + /** \see BOOST_YAP_USER_EXPR_IF_ELSE for full semantics. */ + template + constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3); + +#endif + + /** Returns make_expression(...). + */ + template + constexpr auto make_expression(T &&... t) + { + return make_expression(static_cast(t)...); + } + + /** Returns make_terminal(t). */ + template + constexpr auto make_terminal(T && t) + { + return make_terminal(static_cast(t)); + } + + /** Returns as_expr(t). */ + template + constexpr decltype(auto) as_expr(T && t) + { + return as_expr(static_cast(t)); + } + +}} + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_dev/print.hpp b/third-party/boost_1_72_0/boost/yap_dev/print.hpp new file mode 100644 index 0000000..c97e2f3 --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_dev/print.hpp @@ -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 + +#include +#include +#include + + +namespace boost { namespace yap { + + /** Returns the char const * 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 + expr_kind::expr_ref amd expr_kind::terminal, + 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> + struct printer + { + std::ostream & operator()(std::ostream & os, T const &) + { + return os << "<>"; + } + }; + + template + struct printer< + T, + void_t() << std::declval())>> + { + std::ostream & operator()(std::ostream & os, T const & x) + { + return os << x; + } + }; + + template + inline std::ostream & print_value(std::ostream & os, T const & x) + { + return printer{}(os, x); + } + + template + inline std::ostream & print_value(std::ostream & os, hana::llong) + { + return os << I << "_p"; + } + + template + std::ostream & print_type(std::ostream & os, hana::tuple const &) + { + os << typeindex::type_id().pretty_name(); + if (std::is_const::value) + os << " const"; + if (std::is_volatile::value) + os << " volatile"; + if (std::is_lvalue_reference::value) + os << " &"; + if (std::is_rvalue_reference::value) + os << " &&"; + return os; + } + + template + bool is_const_expr_ref(T const &) + { + return false; + } + template class expr_template> + bool is_const_expr_ref( + expr_template> const &) + { + return true; + } + +#ifdef BOOST_NO_CONSTEXPR_IF + + template + struct print_impl + { + template + 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::kind; + print_impl{}(os, element, indent + 1, indent_str); + }); + + return os; + } + }; + + template<> + struct print_impl + { + template + 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::kind; + print_impl{}( + os, + ::boost::yap::deref(expr), + indent, + indent_str, + true, + ::boost::yap::detail::is_const_expr_ref(expr)); + return os; + } + }; + + template<> + struct print_impl + { + template + 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 + 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 + std::ostream & print(std::ostream & os, Expr const & expr) + { +#ifdef BOOST_NO_CONSTEXPR_IF + return detail::print_impl::kind>{}( + os, expr, 0, " "); +#else + return detail::print_impl(os, expr, 0, " "); +#endif + } + +}} + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_dev/user_macros.hpp b/third-party/boost_1_72_0/boost/yap_dev/user_macros.hpp new file mode 100644 index 0000000..f00a99d --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_dev/user_macros.hpp @@ -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 +#include +#include +#include + + +#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 const &, + &, and &&. 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 expr_kind, without the + expr_kind:: 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 const & x) \ + { \ + using lhs_type = ::boost::yap::detail::operand_type_t< \ + result_expr_template, \ + expr_template const &>; \ + using tuple_type = ::boost::hana::tuple; \ + return result_expr_template< \ + ::boost::yap::expr_kind::op_name, \ + tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(x)}}; \ + } \ + template<::boost::yap::expr_kind Kind, typename Tuple> \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + expr_template & x) \ + { \ + using lhs_type = ::boost::yap::detail::operand_type_t< \ + result_expr_template, \ + expr_template &>; \ + using tuple_type = ::boost::hana::tuple; \ + return result_expr_template< \ + ::boost::yap::expr_kind::op_name, \ + tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(x)}}; \ + } \ + template<::boost::yap::expr_kind Kind, typename Tuple> \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + expr_template && x) \ + { \ + using tuple_type = ::boost::hana::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 const + &, &, and &&. For the lvalue reference + overloads, *this is captured by reference into the resulting + expression. For the rvalue reference overload, *this 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 expr_kind, except assign, subscript, or + call, without the expr_kind:: 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 const & lhs, Expr && rhs) \ + { \ + using lhs_type = ::boost::yap::detail::operand_type_t< \ + result_expr_template, \ + expr_template const &>; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return result_expr_template< \ + ::boost::yap::expr_kind::op_name, \ + tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(lhs), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + expr_template & lhs, Expr && rhs) \ + { \ + using lhs_type = ::boost::yap::detail::operand_type_t< \ + result_expr_template, \ + expr_template &>; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return result_expr_template< \ + ::boost::yap::expr_kind::op_name, \ + tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(lhs), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template<::boost::yap::expr_kind Kind, typename Tuple, typename Expr> \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + expr_template && lhs, Expr && rhs) \ + { \ + using lhs_type = ::boost::yap::detail::remove_cv_ref_t< \ + expr_template &&>; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return result_expr_template< \ + ::boost::yap::expr_kind::op_name, \ + tuple_type>{ \ + tuple_type{std::move(lhs), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + T && lhs, expr_template && rhs) \ + ->::boost::yap::detail::free_binary_op_result_t< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template &&> \ + { \ + using result_types = ::boost::yap::detail::free_binary_op_result< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template &&>; \ + using lhs_type = typename result_types::lhs_type; \ + using rhs_type = typename result_types::rhs_type; \ + using tuple_type = ::boost::hana::tuple; \ + return {tuple_type{lhs_type{static_cast(lhs)}, std::move(rhs)}}; \ + } \ + template \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + T && lhs, expr_template const & rhs) \ + ->::boost::yap::detail::free_binary_op_result_t< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template const &> \ + { \ + using result_types = ::boost::yap::detail::free_binary_op_result< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template const &>; \ + using lhs_type = typename result_types::lhs_type; \ + using rhs_type = typename result_types::rhs_type; \ + using tuple_type = ::boost::hana::tuple; \ + using rhs_tuple_type = typename result_types::rhs_tuple_type; \ + return {tuple_type{lhs_type{static_cast(lhs)}, \ + rhs_type{rhs_tuple_type{std::addressof(rhs)}}}}; \ + } \ + template \ + constexpr auto operator BOOST_YAP_INDIRECT_CALL(op_name)( \ + T && lhs, expr_template & rhs) \ + ->::boost::yap::detail::free_binary_op_result_t< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template &> \ + { \ + using result_types = ::boost::yap::detail::free_binary_op_result< \ + result_expr_template, \ + ::boost::yap::expr_kind::op_name, \ + T, \ + expr_template &>; \ + using lhs_type = typename result_types::lhs_type; \ + using rhs_type = typename result_types::rhs_type; \ + using tuple_type = ::boost::hana::tuple; \ + using rhs_tuple_type = typename result_types::rhs_tuple_type; \ + return {tuple_type{lhs_type{static_cast(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 const &, + &, and &&. For the lvalue reference overloads, + *this is captured by reference into the resulting expression. + For the rvalue reference overload, *this 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::value>> \ + constexpr auto operator=(Expr && rhs) const & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template< \ + typename Expr, \ + typename = std::enable_if_t< \ + !::boost::yap::detail::copy_or_move::value>> \ + constexpr auto operator=(Expr && rhs) & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template< \ + typename Expr, \ + typename = std::enable_if_t< \ + !::boost::yap::detail::copy_or_move::value>> \ + constexpr auto operator=(Expr && rhs) && \ + { \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::assign, tuple_type>{ \ + tuple_type{std::move(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(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 const &, + &, and &&. For the lvalue reference overloads, + *this is captured by reference into the resulting expression. + For the rvalue reference overload, *this 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 \ + constexpr auto operator[](Expr && rhs) const & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template \ + constexpr auto operator[](Expr && rhs) & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ + tuple_type{::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(rhs))}}; \ + } \ + template \ + constexpr auto operator[](Expr && rhs) && \ + { \ + using lhs_type = \ + ::boost::yap::detail::remove_cv_ref_t; \ + using rhs_type = \ + ::boost::yap::detail::operand_type_t; \ + using tuple_type = ::boost::hana::tuple; \ + return expr_template<::boost::yap::expr_kind::subscript, tuple_type>{ \ + tuple_type{std::move(*this), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(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 const &, &, and + &&. For the lvalue reference overloads, *this + is captured by reference into the resulting expression. For the rvalue + reference overload, *this 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 \ + constexpr auto operator()(U &&... u) const & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using tuple_type = ::boost::hana::tuple< \ + lhs_type, \ + ::boost::yap::detail::operand_type_t...>; \ + return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ + tuple_type{ \ + ::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand< \ + ::boost::yap::detail::operand_type_t>{}( \ + static_cast(u))...}}; \ + } \ + template \ + constexpr auto operator()(U &&... u) & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + using tuple_type = ::boost::hana::tuple< \ + lhs_type, \ + ::boost::yap::detail::operand_type_t...>; \ + return expr_template<::boost::yap::expr_kind::call, tuple_type>{ \ + tuple_type{ \ + ::boost::yap::detail::make_operand{}(*this), \ + ::boost::yap::detail::make_operand< \ + ::boost::yap::detail::operand_type_t>{}( \ + static_cast(u))...}}; \ + } \ + template \ + constexpr auto operator()(U &&... u) && \ + { \ + using this_type = \ + ::boost::yap::detail::remove_cv_ref_t; \ + using tuple_type = ::boost::hana::tuple< \ + this_type, \ + ::boost::yap::detail::operand_type_t...>; \ + 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>{}( \ + static_cast(u))...}}; \ + } + + +#ifndef BOOST_YAP_DOXYGEN + +#define BOOST_YAP_USER_CALL_OPERATOR_OPERAND_T(z, n, expr_template) \ + ::boost::yap::detail::operand_type_t +#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))) + +#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 const &, + &, and &&. For the lvalue reference overloads, + *this is captured by reference into the resulting expression. + For the rvalue reference overload, *this 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 \ + constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) const & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + 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{}(*this), \ + BOOST_PP_ENUM( \ + n, \ + BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \ + expr_template)}}; \ + } \ + template \ + constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) & \ + { \ + using lhs_type = ::boost::yap::detail:: \ + operand_type_t; \ + 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{}(*this), \ + BOOST_PP_ENUM( \ + n, \ + BOOST_YAP_USER_CALL_OPERATOR_MAKE_OPERAND, \ + expr_template)}}; \ + } \ + template \ + constexpr auto operator()(BOOST_PP_ENUM_BINARY_PARAMS(n, U, &&u)) && \ + { \ + using this_type = \ + ::boost::yap::detail::remove_cv_ref_t; \ + 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 if_else() that acts as an + analogue to the ternary operator (?:), since the ternary + operator is not user-overloadable. The return type of + if_else() is an expression instantiated from the \a + expr_template expression template. + + At least one parameter to if_else() must be an expression. + + For each parameter E passed to if_else(), 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 \ + constexpr auto if_else(Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \ + ->::boost::yap::detail:: \ + ternary_op_result_t \ + { \ + using result_types = ::boost::yap::detail:: \ + ternary_op_result; \ + 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; \ + return {tuple_type{::boost::yap::detail::make_operand{}( \ + static_cast(expr1)), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(expr2)), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(expr3))}}; \ + } + + +/** Defines a function if_else() that acts as an analogue to the + ternary operator (?:), since the ternary operator is not + user-overloadable. The return type of if_else() is an + expression instantiated from the \a expr_template expression template. + + Each parameter to if_else() may be any type that is \b not an + expression. At least on parameter must be a type T for which + \code udt_trait>>::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 if_else(). +*/ +#define BOOST_YAP_USER_UDT_ANY_IF_ELSE(expr_template, udt_trait) \ + template \ + 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; \ + return {tuple_type{::boost::yap::detail::make_operand{}( \ + static_cast(expr1)), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(expr2)), \ + ::boost::yap::detail::make_operand{}( \ + static_cast(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>>::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 expr_kind, without the + expr_kind:: 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 \ + 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; \ + return {tuple_type{x_type{static_cast(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>>::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>>::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 expr_kind, without the + expr_kind:: 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 \ + 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; \ + return {tuple_type{ \ + lhs_type{static_cast(lhs)}, \ + rhs_type{static_cast(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>>::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 expr_kind, without the + expr_kind:: 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 \ + 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; \ + return {tuple_type{lhs_type{static_cast(lhs)}, \ + rhs_type{static_cast(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 \ + constexpr auto operator"" _p() \ + { \ + using i = ::boost::hana::llong< \ + ::boost::hana::ic_detail::parse({c...})>; \ + static_assert(1 <= i::value, "Placeholders must be >= 1."); \ + return expr_template< \ + ::boost::yap::expr_kind::terminal, \ + ::boost::hana::tuple<::boost::yap::placeholder>>{}; \ + } + +#endif diff --git a/third-party/boost_1_72_0/boost/yap_dev/yap.hpp b/third-party/boost_1_72_0/boost/yap_dev/yap.hpp new file mode 100644 index 0000000..25ef433 --- /dev/null +++ b/third-party/boost_1_72_0/boost/yap_dev/yap.hpp @@ -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 +#include + +#endif