#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); }