mirror of
https://github.com/boostorg/yap.git
synced 2026-02-26 05:12:13 +00:00
Add if_else pseudo-operator.
This commit is contained in:
@@ -130,6 +130,15 @@ namespace boost::proto17 {
|
||||
BOOST_PROTO17_BINARY_OPERATOR_CASE(bitwise_xor_assign) // ^=
|
||||
BOOST_PROTO17_BINARY_OPERATOR_CASE(subscript) // []
|
||||
|
||||
else if constexpr (kind == expr_kind::if_else) {
|
||||
return
|
||||
eval_if_else(
|
||||
default_eval_expr(expr.elements[0_c], static_cast<T &&>(args)...),
|
||||
default_eval_expr(expr.elements[1_c], static_cast<T &&>(args)...),
|
||||
default_eval_expr(expr.elements[2_c], static_cast<T &&>(args)...)
|
||||
);
|
||||
}
|
||||
|
||||
#undef BOOST_PROTO17_BINARY_OPERATOR_CASE
|
||||
|
||||
else if constexpr (kind == expr_kind::call) {
|
||||
|
||||
@@ -242,6 +242,95 @@ namespace boost::proto17 {
|
||||
>::type;
|
||||
|
||||
|
||||
// ternary_op_result
|
||||
|
||||
template <
|
||||
template <expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V,
|
||||
bool Valid = is_expr<T>::value || is_expr<U>::value || is_expr<V>::value
|
||||
>
|
||||
struct ternary_op_result;
|
||||
|
||||
template <
|
||||
template <expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V
|
||||
>
|
||||
struct ternary_op_result<ExprTemplate, T, U, V, true>
|
||||
{
|
||||
using cond_type = operand_type_t<ExprTemplate, T>;
|
||||
using then_type = operand_type_t<ExprTemplate, U>;
|
||||
using else_type = operand_type_t<ExprTemplate, V>;
|
||||
using type = ExprTemplate<
|
||||
expr_kind::if_else,
|
||||
hana::tuple<cond_type, then_type, else_type>
|
||||
>;
|
||||
};
|
||||
|
||||
template <
|
||||
template <expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V
|
||||
>
|
||||
using ternary_op_result_t = typename ternary_op_result<ExprTemplate, T, U, V>::type;
|
||||
|
||||
|
||||
// udt_any_ternary_op_result
|
||||
|
||||
template <
|
||||
template <expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V,
|
||||
template <class> class UdtTrait,
|
||||
bool Valid =
|
||||
!is_expr<T>::value && !is_expr<U>::value && !is_expr<V>::value &&
|
||||
(
|
||||
UdtTrait<remove_cv_ref_t<T>>::value ||
|
||||
UdtTrait<remove_cv_ref_t<U>>::value ||
|
||||
UdtTrait<remove_cv_ref_t<V>>::value
|
||||
)
|
||||
>
|
||||
struct udt_any_ternary_op_result;
|
||||
|
||||
template <
|
||||
template <expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V,
|
||||
template <class> class UdtTrait
|
||||
>
|
||||
struct udt_any_ternary_op_result<ExprTemplate, T, U, V, UdtTrait, true>
|
||||
{
|
||||
using cond_type = operand_type_t<ExprTemplate, T>;
|
||||
using then_type = operand_type_t<ExprTemplate, U>;
|
||||
using else_type = operand_type_t<ExprTemplate, V>;
|
||||
using type = ExprTemplate<
|
||||
expr_kind::if_else,
|
||||
hana::tuple<cond_type, then_type, else_type>
|
||||
>;
|
||||
};
|
||||
|
||||
template <
|
||||
template <expr_kind, class> class ExprTemplate,
|
||||
typename T,
|
||||
typename U,
|
||||
typename V,
|
||||
template <class> class UdtTrait
|
||||
>
|
||||
using udt_any_ternary_op_result_t = typename udt_any_ternary_op_result<
|
||||
ExprTemplate,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
UdtTrait
|
||||
>::type;
|
||||
|
||||
|
||||
// udt_unary_op_result
|
||||
|
||||
template <
|
||||
@@ -339,8 +428,7 @@ namespace boost::proto17 {
|
||||
typename U,
|
||||
template <class> class UdtTrait,
|
||||
bool Valid =
|
||||
!is_expr<T>::value &&
|
||||
!is_expr<U>::value &&
|
||||
!is_expr<T>::value && !is_expr<U>::value &&
|
||||
(UdtTrait<remove_cv_ref_t<T>>::value || UdtTrait<remove_cv_ref_t<U>>::value)
|
||||
>
|
||||
struct udt_any_binary_op_result;
|
||||
@@ -381,6 +469,7 @@ namespace boost::proto17 {
|
||||
invalid,
|
||||
one,
|
||||
two,
|
||||
three,
|
||||
n
|
||||
};
|
||||
|
||||
@@ -441,6 +530,10 @@ namespace boost::proto17 {
|
||||
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;
|
||||
@@ -509,6 +602,9 @@ namespace boost::proto17 {
|
||||
CASE(bitwise_xor_assign); // ^=
|
||||
CASE(subscript); // []
|
||||
|
||||
// ternary
|
||||
CASE(if_else); // (analogous to) ?:
|
||||
|
||||
// n-ary
|
||||
CASE(call); // ()
|
||||
|
||||
|
||||
@@ -80,6 +80,8 @@ namespace boost::proto17 {
|
||||
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! **";
|
||||
@@ -407,6 +409,8 @@ namespace boost::proto17 {
|
||||
|
||||
#undef BOOST_PROTO17_BINARY_FREE_OPERATOR
|
||||
|
||||
BOOST_PROTO17_USER_EXPR_IF_ELSE(::boost::proto17::expression)
|
||||
|
||||
template <expr_kind Kind, typename ...T>
|
||||
auto make_expression (T &&... t)
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace boost::proto17 {
|
||||
subscript, // []
|
||||
|
||||
// ternary
|
||||
// TODO: if_else, // (analogous to) ?:
|
||||
if_else, // (analogous to) ?:
|
||||
|
||||
// n-ary
|
||||
call // ()
|
||||
@@ -161,6 +161,9 @@ namespace boost::proto17 {
|
||||
struct bitwise_xor_assign_tag {}; // ^=
|
||||
struct subscript_tag {}; // []
|
||||
|
||||
// ternary
|
||||
struct if_else_tag {}; // (analogous to) ?:
|
||||
|
||||
// n-ary
|
||||
struct call_tag {}; // ()
|
||||
|
||||
|
||||
@@ -128,6 +128,18 @@ namespace boost::proto17 {
|
||||
|
||||
#undef BOOST_PROTO17_BINARY_OPERATOR
|
||||
|
||||
template <typename T, typename U, typename V>
|
||||
constexpr auto eval_if_else (T && t, U && u, V && v) BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN(
|
||||
static_cast<T &&>(t) ? static_cast<U &&>(u) : static_cast<V &&>(v)
|
||||
)
|
||||
struct eval_if_else_fn
|
||||
{
|
||||
template <typename T, typename U, typename V>
|
||||
constexpr auto operator() (T && t, U && u, V && v) const BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN(
|
||||
eval_if_else(static_cast<T &&>(t), static_cast<U &&>(u), static_cast<V &&>(v))
|
||||
)
|
||||
};
|
||||
|
||||
template <typename F, typename ...T>
|
||||
constexpr auto eval_call (F && f, T && ...t) BOOST_PROTO17_NOEXCEPT_DECLTYPE_RETURN(
|
||||
static_cast<F &&>(f)(static_cast<T &&>(t)...)
|
||||
@@ -188,6 +200,7 @@ namespace boost::proto17 {
|
||||
BOOST_PROTO17_USING_OPERATOR_FN(bitwise_or_assign) // |=
|
||||
BOOST_PROTO17_USING_OPERATOR_FN(bitwise_xor_assign) // ^=
|
||||
BOOST_PROTO17_USING_OPERATOR_FN(subscript) // []
|
||||
BOOST_PROTO17_USING_OPERATOR_FN(if_else) // (analogous to) ?:
|
||||
BOOST_PROTO17_USING_OPERATOR_FN(call) // ()
|
||||
|
||||
#undef BOOST_PROTO17_USING_OPERATOR_FN
|
||||
@@ -239,6 +252,7 @@ namespace boost::proto17 {
|
||||
BOOST_PROTO17_DECLARE_OPERATOR_FN(bitwise_or_assign) // |=
|
||||
BOOST_PROTO17_DECLARE_OPERATOR_FN(bitwise_xor_assign) // ^=
|
||||
BOOST_PROTO17_DECLARE_OPERATOR_FN(subscript) // []
|
||||
BOOST_PROTO17_DECLARE_OPERATOR_FN(if_else) // (analogous to) ?:
|
||||
BOOST_PROTO17_DECLARE_OPERATOR_FN(call) // ()
|
||||
|
||||
#undef BOOST_PROTO17_DECLARE_OPERATOR_FN
|
||||
|
||||
@@ -214,6 +214,68 @@
|
||||
} \
|
||||
|
||||
|
||||
#define BOOST_PROTO17_USER_EXPR_IF_ELSE(expr_template) \
|
||||
template <typename Expr1, typename Expr2, typename Expr3> \
|
||||
auto if_else (Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \
|
||||
-> ::boost::proto17::detail::ternary_op_result_t< \
|
||||
expr_template, \
|
||||
Expr1, \
|
||||
Expr2, \
|
||||
Expr3 \
|
||||
> \
|
||||
{ \
|
||||
using result_types = ::boost::proto17::detail::ternary_op_result< \
|
||||
expr_template, \
|
||||
Expr1, \
|
||||
Expr2, \
|
||||
Expr3 \
|
||||
>; \
|
||||
using cond_type = typename result_types::cond_type; \
|
||||
using then_type = typename result_types::then_type; \
|
||||
using else_type = typename result_types::else_type; \
|
||||
using tuple_type = ::boost::hana::tuple<cond_type, then_type, else_type>; \
|
||||
return { \
|
||||
tuple_type{ \
|
||||
::boost::proto17::detail::make_operand<cond_type>{}(static_cast<Expr1 &&>(expr1)), \
|
||||
::boost::proto17::detail::make_operand<then_type>{}(static_cast<Expr2 &&>(expr2)), \
|
||||
::boost::proto17::detail::make_operand<else_type>{}(static_cast<Expr3 &&>(expr3)) \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
|
||||
|
||||
#define BOOST_PROTO17_USER_UDT_ANY_IF_ELSE(expr_template, udt_trait) \
|
||||
template <typename Expr1, typename Expr2, typename Expr3> \
|
||||
auto if_else (Expr1 && expr1, Expr2 && expr2, Expr3 && expr3) \
|
||||
-> ::boost::proto17::detail::udt_any_ternary_op_result_t< \
|
||||
expr_template, \
|
||||
Expr1, \
|
||||
Expr2, \
|
||||
Expr3, \
|
||||
udt_trait \
|
||||
> \
|
||||
{ \
|
||||
using result_types = ::boost::proto17::detail::udt_any_ternary_op_result< \
|
||||
expr_template, \
|
||||
Expr1, \
|
||||
Expr2, \
|
||||
Expr3, \
|
||||
udt_trait \
|
||||
>; \
|
||||
using cond_type = typename result_types::cond_type; \
|
||||
using then_type = typename result_types::then_type; \
|
||||
using else_type = typename result_types::else_type; \
|
||||
using tuple_type = ::boost::hana::tuple<cond_type, then_type, else_type>; \
|
||||
return { \
|
||||
tuple_type{ \
|
||||
::boost::proto17::detail::make_operand<cond_type>{}(static_cast<Expr1 &&>(expr1)), \
|
||||
::boost::proto17::detail::make_operand<then_type>{}(static_cast<Expr2 &&>(expr2)), \
|
||||
::boost::proto17::detail::make_operand<else_type>{}(static_cast<Expr3 &&>(expr3)) \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
|
||||
|
||||
#define BOOST_PROTO17_USER_UDT_UNARY_OPERATOR(op_name, expr_template, udt_trait) \
|
||||
template <typename T> \
|
||||
auto operator BOOST_PROTO17_INDIRECT_CALL(op_name)((T && x)) \
|
||||
|
||||
Reference in New Issue
Block a user