[et] tags/separate
This commit is contained in:
parent
6861215065
commit
77e5f927e7
150
examples/et/4_separate.cpp
Normal file
150
examples/et/4_separate.cpp
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#include <cstdio>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
/* **** */
|
||||||
|
/* tags */
|
||||||
|
|
||||||
|
namespace tag {
|
||||||
|
|
||||||
|
struct Add;
|
||||||
|
struct Mul;
|
||||||
|
struct Minus;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ********** */
|
||||||
|
/* expression */
|
||||||
|
|
||||||
|
template<typename Op, typename... Operands>
|
||||||
|
class Expr {
|
||||||
|
std::tuple<Operands...> _operands;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Expr(Operands... operands): _operands{operands...} {}
|
||||||
|
|
||||||
|
template<template<typename> class Evaluator>
|
||||||
|
auto eval() const {
|
||||||
|
return eval<Evaluator>(std::make_index_sequence<sizeof...(Operands)>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<template<typename> class Evaluator, std::size_t... Is>
|
||||||
|
auto eval(std::index_sequence<Is...>) const {
|
||||||
|
return Evaluator<Op>::eval(std::get<Is>(_operands).template eval<Evaluator>()...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Value {
|
||||||
|
T _value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Value(T value): _value(value) {}
|
||||||
|
|
||||||
|
template<template<typename> class>
|
||||||
|
auto eval() const { return _value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* *********** */
|
||||||
|
/* type traits */
|
||||||
|
|
||||||
|
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<tag::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<tag::Mul, LHS, RHS>{lhs, rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename RHS,
|
||||||
|
std::enable_if_t<IsExpr<RHS>>* = nullptr
|
||||||
|
>
|
||||||
|
auto operator-(RHS rhs) {
|
||||||
|
return Expr<tag::Minus, RHS>{rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ********** */
|
||||||
|
/* evaluators */
|
||||||
|
|
||||||
|
template<typename> struct EvaluatorElem;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct EvaluatorElem<tag::Add> {
|
||||||
|
template<typename T>
|
||||||
|
static auto eval(T lhs, T rhs) { return lhs + rhs; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct EvaluatorElem<tag::Mul> {
|
||||||
|
template<typename T>
|
||||||
|
static auto eval(T lhs, T rhs) { return lhs * rhs; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct EvaluatorElem<tag::Minus> {
|
||||||
|
template<typename T>
|
||||||
|
static auto eval(T rhs) { return -rhs; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* *** */
|
||||||
|
|
||||||
|
template<typename> struct EvaluatorBool;
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct EvaluatorBool<tag::Add> {
|
||||||
|
static auto eval(bool lhs, bool rhs) { return lhs or rhs; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct EvaluatorBool<tag::Mul> {
|
||||||
|
static auto eval(bool lhs, bool rhs) { return lhs and rhs; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct EvaluatorBool<tag::Minus> {
|
||||||
|
static auto eval(bool rhs) { return not rhs; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* *** */
|
||||||
|
|
||||||
|
template<template<typename> class Evaluator, typename Expr>
|
||||||
|
auto eval(Expr expr) {
|
||||||
|
return expr.template eval<Evaluator>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int volatile v[]{1, 1, 1};
|
||||||
|
int result;
|
||||||
|
|
||||||
|
Value<int> v0{v[0]}, v1{v[1]}, v2{v[2]};
|
||||||
|
|
||||||
|
auto expr = v0 * -(v1 + v2);
|
||||||
|
|
||||||
|
result = eval<EvaluatorElem>(expr);
|
||||||
|
std::printf("evaluator elem: %d\n", result);
|
||||||
|
|
||||||
|
result = eval<EvaluatorBool>(expr);
|
||||||
|
std::printf("evaluator bool: %d\n", result);
|
||||||
|
}
|
128
examples/et/4_tags.cpp
Normal file
128
examples/et/4_tags.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#include <cstdio>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
/* **** */
|
||||||
|
/* tags */
|
||||||
|
|
||||||
|
namespace tag {
|
||||||
|
|
||||||
|
struct Add {};
|
||||||
|
struct Mul {};
|
||||||
|
struct Minus {};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ********** */
|
||||||
|
/* expression */
|
||||||
|
|
||||||
|
template<typename Op, typename... Operands>
|
||||||
|
class Expr {
|
||||||
|
std::tuple<Operands...> _operands;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Expr(Operands... operands): _operands{operands...} {}
|
||||||
|
|
||||||
|
template<typename Evaluator>
|
||||||
|
auto eval() const {
|
||||||
|
return eval<Evaluator>(std::make_index_sequence<sizeof...(Operands)>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<typename Evaluator, std::size_t... Is>
|
||||||
|
auto eval(std::index_sequence<Is...>) const {
|
||||||
|
return Evaluator::eval(Op{}, std::get<Is>(_operands).template eval<Evaluator>()...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Value {
|
||||||
|
T _value;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Value(T value): _value(value) {}
|
||||||
|
|
||||||
|
template<typename>
|
||||||
|
auto eval() const { return _value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* *********** */
|
||||||
|
/* type traits */
|
||||||
|
|
||||||
|
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<tag::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<tag::Mul, LHS, RHS>{lhs, rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename RHS,
|
||||||
|
std::enable_if_t<IsExpr<RHS>>* = nullptr
|
||||||
|
>
|
||||||
|
auto operator-(RHS rhs) {
|
||||||
|
return Expr<tag::Minus, RHS>{rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ********** */
|
||||||
|
/* evaluators */
|
||||||
|
|
||||||
|
struct EvaluatorElem {
|
||||||
|
template<typename T>
|
||||||
|
static auto eval(tag::Add, T lhs, T rhs) { return lhs + rhs; }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static auto eval(tag::Mul, T lhs, T rhs) { return lhs * rhs; }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static auto eval(tag::Minus, T rhs) { return -rhs; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EvaluatorBool {
|
||||||
|
static auto eval(tag::Add, bool lhs, bool rhs) { return lhs or rhs; }
|
||||||
|
static auto eval(tag::Mul, bool lhs, bool rhs) { return lhs and rhs; }
|
||||||
|
static auto eval(tag::Minus, bool rhs) { return not rhs; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* *** */
|
||||||
|
|
||||||
|
template<typename Evaluator, typename Expr>
|
||||||
|
auto eval(Expr expr) {
|
||||||
|
return expr.template eval<Evaluator>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int volatile v[]{1, 1, 1};
|
||||||
|
int result;
|
||||||
|
|
||||||
|
Value<int> v0{v[0]}, v1{v[1]}, v2{v[2]};
|
||||||
|
|
||||||
|
auto expr = v0 * -(v1 + v2);
|
||||||
|
|
||||||
|
result = eval<EvaluatorElem>(expr);
|
||||||
|
std::printf("evaluator elem: %d\n", result);
|
||||||
|
|
||||||
|
result = eval<EvaluatorBool>(expr);
|
||||||
|
std::printf("evaluator bool: %d\n", result);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user