summaryrefslogtreecommitdiff
path: root/src/array_fun.h
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2014-09-16 21:53:35 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2014-09-16 21:53:35 +0900
commitfa5998ba8535cdf51d204b86ff1290a4a18b2ca0 (patch)
tree532aad31a1caefab1ed93b5627ecc55dac56b5f9 /src/array_fun.h
parentb63c1dce08e15ef7a533c309ac607fa2d11a96f6 (diff)
Rewrite expression template to make it a bit easier
Diffstat (limited to 'src/array_fun.h')
-rw-r--r--src/array_fun.h110
1 files changed, 54 insertions, 56 deletions
diff --git a/src/array_fun.h b/src/array_fun.h
index 80a56046..9a749c01 100644
--- a/src/array_fun.h
+++ b/src/array_fun.h
@@ -75,91 +75,89 @@ public:
namespace expr {
-template<typename L, typename OpTag, typename R>
+template<typename L, typename R, typename Op>
struct BinExpr {
- BinExpr(L l, R r):l_(l), r_(r) {}
+ typedef typename Op::result_type value_type;
- typedef typename OpTag::returnType returnType;
+ BinExpr(L lhs, R rhs, Op op)
+ : lhs(std::move(lhs)), rhs(std::move(rhs)), op(std::move(op))
+ {}
- returnType operator[](size_t index) const
+ value_type operator[](size_t i) const
{
- return OpTag::apply(l_[index], r_[index]);
+ return op(lhs[i], rhs[i]);
}
- const L l_;
- const R r_;
+ L lhs;
+ R rhs;
+ Op op;
};
-template<typename OpTag, typename A>
+template<typename L, typename R,
+ typename Op = std::bit_and<typename L::value_type>>
+BinExpr<L, R, Op> operator&(L lhs, R rhs)
+{
+ return BinExpr<L, R, Op>(std::forward<L>(lhs), std::forward<R>(rhs), Op());
+}
+
+template<typename L, typename R,
+ typename Op = std::bit_or<typename L::value_type>>
+BinExpr<L, R, Op> operator|(L lhs, R rhs)
+{
+ return BinExpr<L, R, Op>(std::forward<L>(lhs), std::forward<R>(rhs), Op());
+}
+
+template<typename Arg, typename Op>
struct UnExpr {
- UnExpr(A a):a_(a) {}
+ typedef typename Op::result_type value_type;
- typedef typename OpTag::returnType returnType;
+ UnExpr(Arg arg, Op op)
+ : arg(std::move(arg)), op(std::move(op))
+ {}
- returnType operator[](size_t index) const
+ value_type operator[](size_t i) const
{
- return OpTag::apply(a_[index]);
+ return op(arg[i]);
}
- const A a_;
+ Arg arg;
+ Op op;
};
template<typename T>
-struct And
-{
- typedef T returnType;
- static inline returnType apply(T lhs, T rhs) { return lhs&rhs; }
-};
-
-template<typename T>
-struct Or
-{
- typedef T returnType;
- static inline returnType apply(T lhs, T rhs) { return lhs|rhs; }
+struct bit_neg : std::function<T(T)> {
+ T operator()(T t) const
+ {
+ return ~t;
+ }
};
-template<typename T>
-struct Negate
+template<typename Arg, typename Op = bit_neg<typename Arg::value_type>>
+UnExpr<Arg, Op> operator~(Arg arg)
{
- typedef T returnType;
- static inline returnType apply(T a) { return ~a; }
-};
+ return UnExpr<Arg, Op>(std::forward<Arg>(arg), Op());
+}
template<typename T>
-struct Array
-{
- typedef T returnType;
+struct Array {
+ typedef T value_type;
- Array(const T* t):t_(t) {}
+ Array(T* t)
+ : t(t)
+ {}
- const T* t_;
+ T operator[](size_t i) const
+ {
+ return t[i];
+ }
- returnType operator[](size_t index) const { return t_[index]; }
+ T* t;
};
template<typename T>
-Array<T>
-array(const T* t) { return Array<T>(t); }
-
-template<typename L, typename R>
-BinExpr<L, And<typename L::returnType>, R>
-operator&(const L& l, const R& r)
-{
- return BinExpr<L, And<typename L::returnType>, R>(l, r);
-}
-
-template<typename L, typename R>
-BinExpr<L, Or<typename L::returnType>, R>
-operator|(const L& l, const R& r)
-{
- return BinExpr<L, Or<typename L::returnType>, R>(l, r);
-}
-
-template<typename A>
-UnExpr<Negate<typename A::returnType>, A>
-operator~(const A& a)
+Array<T> array(T *t)
{
- return UnExpr<Negate<typename A::returnType>, A>(a);
+ return Array<T>(t);
}
} // namespace expr