#ifndef PFOR_PFOR_EXPRESSION_OPERATORS_H #define PFOR_PFOR_EXPRESSION_OPERATORS_H #include "asexpression.h" #include "expression.h" #include "op.h" #define PFOR_EXPR_DEF_UN_OP(OP, OPSYM) \ template>* = nullptr> \ inline auto operator OPSYM(T const& t) { return Expression{{}, t}; } #define PFOR_EXPR_DEF_BIN_OP(OP, OPSYM) \ template>* = nullptr> \ inline auto operator OPSYM(Lhs const& lhs, Rhs const& rhs) { \ return Expression, AsExpression>{{}, lhs, rhs}; \ } #define PFOR_EXPR_DEF_OPS() \ PFOR_EXPR_DEF_UN_OP (op::Plus, +) \ PFOR_EXPR_DEF_UN_OP (op::Minus, -) \ PFOR_EXPR_DEF_UN_OP (op::Not, !) \ PFOR_EXPR_DEF_UN_OP (op::BitNot, ~) \ PFOR_EXPR_DEF_UN_OP (op::Indirection, *) \ PFOR_EXPR_DEF_UN_OP (op::AddressOf, &) \ \ PFOR_EXPR_DEF_BIN_OP(op::Multiplication, *) \ PFOR_EXPR_DEF_BIN_OP(op::Division, /) \ PFOR_EXPR_DEF_BIN_OP(op::Modulo, %) \ PFOR_EXPR_DEF_BIN_OP(op::Addition, +) \ PFOR_EXPR_DEF_BIN_OP(op::Subtraction, -) \ PFOR_EXPR_DEF_BIN_OP(op::LeftShift, <<) \ PFOR_EXPR_DEF_BIN_OP(op::RightShift, >>) \ PFOR_EXPR_DEF_BIN_OP(op::Lower, <) \ PFOR_EXPR_DEF_BIN_OP(op::LowerEqual, <=) \ PFOR_EXPR_DEF_BIN_OP(op::Greater, >) \ PFOR_EXPR_DEF_BIN_OP(op::GreaterEqual, >=) \ PFOR_EXPR_DEF_BIN_OP(op::Equal, ==) \ PFOR_EXPR_DEF_BIN_OP(op::NotEqual, !=) \ PFOR_EXPR_DEF_BIN_OP(op::BitAnd, &) \ PFOR_EXPR_DEF_BIN_OP(op::BitXor, ^) \ PFOR_EXPR_DEF_BIN_OP(op::BitOr, |) \ PFOR_EXPR_DEF_BIN_OP(op::And, &&) \ PFOR_EXPR_DEF_BIN_OP(op::Or, ||) \ PFOR_EXPR_DEF_BIN_OP(op::AssignAdd, +=) \ PFOR_EXPR_DEF_BIN_OP(op::AssignSub, -=) \ PFOR_EXPR_DEF_BIN_OP(op::AssignMul, *=) \ PFOR_EXPR_DEF_BIN_OP(op::AssignDiv, /=) \ PFOR_EXPR_DEF_BIN_OP(op::AssignMod, %=) \ PFOR_EXPR_DEF_BIN_OP(op::AssignLS, <<=) \ PFOR_EXPR_DEF_BIN_OP(op::AssignRS, >>=) \ PFOR_EXPR_DEF_BIN_OP(op::AssignAnd, &=) \ PFOR_EXPR_DEF_BIN_OP(op::AssignXor, ^=) \ PFOR_EXPR_DEF_BIN_OP(op::AssignOr, |=) namespace pfor { namespace expr { PFOR_EXPR_DEF_OPS(); template inline decltype(auto) If(Cond const& cond, T const& t, F const& f) { return Expression{{}, cond, t, f}; } /** */ template struct CommaMergerImpl; template struct CommaMergerImpl, Expression> { using type = Expression, Expression>; }; template struct CommaMergerImpl, Expression> { using type = Expression>; }; template struct CommaMergerImpl, Expression> { using type = Expression, RTs...>; }; template struct CommaMergerImpl, Expression> { using type = Expression; }; template using CommaMerger = typename CommaMergerImpl::type; /** */ template>* = nullptr> inline auto commaMerger(Ts... ts) { return Expression{{}, ts...}; } template inline auto commaMerger(std::tuple const& lhs, std::index_sequence const&, std::tuple const& rhs, std::index_sequence const&) { return Expression{{}, std::get(lhs)..., std::get(rhs)...}; } template::value>* = nullptr, std::enable_if_t::value>* = nullptr> inline auto operator,(Expression const& lhs, Expression const& rhs) { using Lhs = Expression; using Rhs = Expression; return CommaMerger{{}, lhs, rhs}; } template::value>* = nullptr> inline auto operator,(Expression const& lhs, Expression const& rhs) { return commaMerger(std::make_tuple(lhs), std::make_index_sequence<1>{}, rhs.operands, std::make_index_sequence{}); } template::value>* = nullptr> inline auto operator,(Expression const& lhs, Expression const& rhs) { return commaMerger(lhs.operands, std::make_index_sequence{}, std::make_tuple(rhs), std::make_index_sequence<1>{}); } template inline auto operator,(Expression const& lhs, Expression const& rhs) { return commaMerger(lhs.operands, std::make_index_sequence{}, rhs.operands, std::make_index_sequence{}); } } } #undef PFOR_EXPR_DEF_UN_OP #undef PFOR_EXPR_DEF_BIN_OP #undef PFOR_EXPR_DEF_OPS #endif