#ifndef PFOR_PFOR_EXPRESSION_OP_H #define PFOR_PFOR_EXPRESSION_OP_H #include "access.h" #include "optraits.h" #include "traits.h" #define PFOR_EXPR_DEF_OPERATION_UNARY(OPNAME, OPSYM) \ struct OPNAME { \ template>* = nullptr> \ inline static decltype(auto) eval(T&& value) { \ return OPSYM std::forward(value).eval(); \ } \ template \ inline static decltype(auto) eval(long i, T&& value) { \ return OPSYM std::forward(value)[i]; \ } \ } #define PFOR_EXPR_DEF_OPERATION_POST_UNARY(OPNAME, OPSYM) \ struct OPNAME { \ template>* = nullptr> \ inline static decltype(auto) eval(T&& value) { \ return std::forward(value).eval() OPSYM; \ } \ template \ inline static decltype(auto) eval(long i, T&& value) { \ return std::forward(value)[i] OPSYM; \ } \ } #define PFOR_EXPR_DEF_OPERATION_BINARY(OPNAME, OPSYM) \ struct OPNAME { \ template>* = nullptr> \ inline static decltype(auto) eval(Lhs&& lhs, Rhs&& rhs) { \ return std::forward(lhs).eval() OPSYM std::forward(rhs).eval(); \ } \ template \ inline static decltype(auto) eval(long i, Lhs&& lhs, Rhs&& rhs) { \ return std::forward(lhs)[i] OPSYM std::forward(rhs)[i]; \ } \ } namespace pfor { namespace expr { namespace op { /* from: http://en.cppreference.com/w/cpp/language/operator_precedence * excluding non overloadable operators * * [02] a++, a--, a(), a[] * [03] ++a, --a, +a, -a, !a, ~a, *a, &a * [04] ->* * [05] a*b, a/b, a%b * [06] a+b, a-b * [07] <<, >> * [08] <, <=, >, >= * [09] ==, != * [10] a&b * [11] ^ * [12] | * [13] && * [14] || * [15] =, +=, -=, *=, /=, %=, <<=, >>=, &=, ^=, |= * [16] , */ /* ===== Unary ===== */ PFOR_EXPR_DEF_OPERATION_POST_UNARY(PostIncr, ++); PFOR_EXPR_DEF_OPERATION_POST_UNARY(PostDecr, --); PFOR_EXPR_DEF_OPERATION_UNARY(PreIncr, ++); PFOR_EXPR_DEF_OPERATION_UNARY(PreDecr, --); PFOR_EXPR_DEF_OPERATION_UNARY(Plus, +); PFOR_EXPR_DEF_OPERATION_UNARY(Minus, -); PFOR_EXPR_DEF_OPERATION_UNARY(Not, !); PFOR_EXPR_DEF_OPERATION_UNARY(BitNot, ~); PFOR_EXPR_DEF_OPERATION_UNARY(Indirection, *); PFOR_EXPR_DEF_OPERATION_UNARY(AddressOf, &); /* ===== Binary ===== */ PFOR_EXPR_DEF_OPERATION_BINARY(PtrToMem, ->*); PFOR_EXPR_DEF_OPERATION_BINARY(Multiplication, *); PFOR_EXPR_DEF_OPERATION_BINARY(Division, /); PFOR_EXPR_DEF_OPERATION_BINARY(Modulo, %); PFOR_EXPR_DEF_OPERATION_BINARY(Addition, +); PFOR_EXPR_DEF_OPERATION_BINARY(Subtraction, -); PFOR_EXPR_DEF_OPERATION_BINARY(LeftShift, <<); PFOR_EXPR_DEF_OPERATION_BINARY(RightShift, >>); PFOR_EXPR_DEF_OPERATION_BINARY(Lower, <); PFOR_EXPR_DEF_OPERATION_BINARY(LowerEqual, <=); PFOR_EXPR_DEF_OPERATION_BINARY(Greater, >); PFOR_EXPR_DEF_OPERATION_BINARY(GreaterEqual, >=); PFOR_EXPR_DEF_OPERATION_BINARY(Equal, ==); PFOR_EXPR_DEF_OPERATION_BINARY(NotEqual, !=); PFOR_EXPR_DEF_OPERATION_BINARY(BitAnd, &); PFOR_EXPR_DEF_OPERATION_BINARY(BitXor, ^); PFOR_EXPR_DEF_OPERATION_BINARY(BitOr, |); PFOR_EXPR_DEF_OPERATION_BINARY(And, &&); PFOR_EXPR_DEF_OPERATION_BINARY(Or, ||); PFOR_EXPR_DEF_OPERATION_BINARY(Assign, =); PFOR_EXPR_DEF_OPERATION_BINARY(AssignAdd, +=); PFOR_EXPR_DEF_OPERATION_BINARY(AssignSub, -=); PFOR_EXPR_DEF_OPERATION_BINARY(AssignMul, *=); PFOR_EXPR_DEF_OPERATION_BINARY(AssignDiv, /=); PFOR_EXPR_DEF_OPERATION_BINARY(AssignMod, %=); PFOR_EXPR_DEF_OPERATION_BINARY(AssignLS, <<=); PFOR_EXPR_DEF_OPERATION_BINARY(AssignRS, >>=); PFOR_EXPR_DEF_OPERATION_BINARY(AssignAnd, &=); PFOR_EXPR_DEF_OPERATION_BINARY(AssignXor, ^=); PFOR_EXPR_DEF_OPERATION_BINARY(AssignOr, |=); struct Subscript { template>* = nullptr> inline static decltype(auto) eval(T&& t, Index&& index) { return std::forward(t).eval()[std::forward(index).eval()]; } template inline static decltype(auto) eval(long i, T&& t, Index&& index) { return std::forward(t)[i][std::forward(index)[i]]; } }; struct Comma { template>* = nullptr> inline static decltype(auto) eval(Lhs&& lhs, Rhs&&... rhs) { return std::forward(lhs).eval(), eval(std::forward(rhs)...); } template>* = nullptr> inline static decltype(auto) eval(Lhs&& lhs, Rhs&& rhs) { return std::forward(lhs).eval(), std::forward(rhs).eval(); } template inline static decltype(auto) eval(long i, Lhs&& lhs, Rhs&&... rhs) { return std::forward(lhs)[i], eval(i, std::forward(rhs)...); } template inline static decltype(auto) eval(long i, Lhs&& lhs, Rhs&& rhs) { return std::forward(lhs)[i], std::forward(rhs)[i]; } template inline static decltype(auto) eval(long i, Lhs&& lhs) { return std::forward(lhs)[i]; } }; /* ===== Ternary ===== */ struct If { template>* = nullptr> inline static decltype(auto) eval(Cond&& cond, T&& t, F&& f) { return std::forward(cond).eval()? std::forward(t).eval():std::forward(f).eval(); } template inline static decltype(auto) eval(long i, Cond&& cond, T&& t, F&& f) { return std::forward(cond)[i]? std::forward(t)[i]:std::forward(f)[i]; } }; /* ==== N-ary ===== */ struct FunctionCall { template>* = nullptr> inline static decltype(auto) eval(F&& f, Ts&&... values) { return std::forward(f).eval()(std::forward(values).eval()...); } template inline static decltype(auto) eval(long i, F&& f, Ts&&... values) { return std::forward(f)[i](std::forward(values)[i]...); } }; #undef PFOR_EXPR_DEF_OPERATION_POST_UNARY #undef PFOR_EXPR_DEF_OPERATION_UNARY #undef PFOR_EXPR_DEF_OPERATION_BINARY template struct View; } #define PFOR_EXPR_SPECIALIZE_ASSIGN(O) \ template \ struct OperationTraits { \ static constexpr Access access = Access::write; \ } PFOR_EXPR_SPECIALIZE_ASSIGN(Assign); PFOR_EXPR_SPECIALIZE_ASSIGN(AssignAdd); PFOR_EXPR_SPECIALIZE_ASSIGN(AssignSub); PFOR_EXPR_SPECIALIZE_ASSIGN(AssignMul); PFOR_EXPR_SPECIALIZE_ASSIGN(AssignDiv); PFOR_EXPR_SPECIALIZE_ASSIGN(AssignMod); PFOR_EXPR_SPECIALIZE_ASSIGN(AssignLS); PFOR_EXPR_SPECIALIZE_ASSIGN(AssignRS); PFOR_EXPR_SPECIALIZE_ASSIGN(AssignAnd); PFOR_EXPR_SPECIALIZE_ASSIGN(AssignXor); PFOR_EXPR_SPECIALIZE_ASSIGN(AssignOr); #undef PFOR_EXPR_SPECIALIZE_ASSIGN } } #endif