mp/examples/et/3_dsl.cpp
2019-07-02 18:16:14 +02:00

88 lines
1.6 KiB
C++

#include <cstdio>
#include <tuple>
/* unchanged from et/2_generic_arity.cpp */
struct Add {
template<typename T>
static auto eval(T lhs, T rhs) {
return lhs + rhs;
}
};
struct Mul {
template<typename T>
static auto eval(T lhs, T rhs) {
return lhs * rhs;
}
};
template<typename T>
class Value {
T _value;
public:
Value(T value): _value(value) {}
auto eval() const { return _value; }
};
template<typename Op, typename... Operands>
class Expr {
std::tuple<Operands...> _operands;
public:
Expr(Operands... operands): _operands{operands...} {}
auto eval() const {
return eval(std::make_index_sequence<sizeof...(Operands)>{});
}
private:
template<std::size_t... Is>
auto eval(std::index_sequence<Is...>) const {
return Op::eval(std::get<Is>(_operands).eval()...);
}
};
/* end of unchanged */
namespace impl {
template<typename T> struct IsExpr: std::false_type {};
template<typename Op, typename... Operands>
struct IsExpr<Expr<Op, Operands...>>: std::true_type {};
template<typename T>
struct IsExpr<Value<T>>: std::true_type {};
}
template<typename T>
constexpr bool IsExpr = impl::IsExpr<T>::value;
template<
typename LHS, typename RHS,
std::enable_if_t<IsExpr<LHS> && IsExpr<RHS>>* = nullptr
>
auto operator+(LHS lhs, RHS rhs) {
return Expr<Add, LHS, RHS>{lhs, rhs};
}
template<
typename LHS, typename RHS,
std::enable_if_t<IsExpr<LHS> && IsExpr<RHS>>* = nullptr
>
auto operator*(LHS lhs, RHS rhs) {
return Expr<Mul, LHS, RHS>{lhs, rhs};
}
int main() {
int volatile v[]{3, 5, 7};
int result;
Value<int> v0{v[0]}, v1{v[1]}, v2{v[2]};
auto expr = v0 + v1 * v2;
result = expr.eval();
std::printf("%d\n", result);
}