2
0
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:
Zach Laine
2016-11-30 22:54:26 -06:00
parent 8631d8383b
commit fabcea271e
6 changed files with 191 additions and 3 deletions

View File

@@ -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) {

View File

@@ -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); // ()

View File

@@ -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)
{

View File

@@ -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 {}; // ()

View File

@@ -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

View File

@@ -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)) \