[et] tags/separate
This commit is contained in:
		
							
								
								
									
										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);
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user