diff --git a/examples/et/3_dsl.cpp b/examples/et/3_dsl.cpp new file mode 100644 index 0000000..4710bb3 --- /dev/null +++ b/examples/et/3_dsl.cpp @@ -0,0 +1,87 @@ +#include +#include + +/* unchanged from et/2_generic_arity.cpp */ +struct Add { + template + static auto eval(T lhs, T rhs) { + return lhs + rhs; + } +}; + +struct Mul { + template + static auto eval(T lhs, T rhs) { + return lhs * rhs; + } +}; + +template +class Value { + T _value; + +public: + Value(T value): _value(value) {} + + auto eval() const { return _value; } +}; + +template +class Expr { + std::tuple _operands; + +public: + Expr(Operands... operands): _operands{operands...} {} + + auto eval() const { + return eval(std::make_index_sequence{}); + } + +private: + template + auto eval(std::index_sequence) const { + return Op::eval(std::get(_operands).eval()...); + } +}; +/* end of unchanged */ + +namespace impl { +template struct IsExpr: std::false_type {}; + +template +struct IsExpr>: std::true_type {}; + +template +struct IsExpr>: std::true_type {}; +} + +template +constexpr bool IsExpr = impl::IsExpr::value; + +template< + typename LHS, typename RHS, + std::enable_if_t && IsExpr>* = nullptr +> +auto operator+(LHS lhs, RHS rhs) { + return Expr{lhs, rhs}; +} + +template< + typename LHS, typename RHS, + std::enable_if_t && IsExpr>* = nullptr +> +auto operator*(LHS lhs, RHS rhs) { + return Expr{lhs, rhs}; +} + +int main() { + int volatile v[]{3, 5, 7}; + int result; + + Value v0{v[0]}, v1{v[1]}, v2{v[2]}; + + auto expr = v0 + v1 * v2; + result = expr.eval(); + + std::printf("%d\n", result); +}