Last active
July 17, 2018 12:19
-
-
Save newlawrence/6f6945fba69bb7e9c6881072f28bd854 to your computer and use it in GitHub Desktop.
C++17 generator of Reduce-able Operators
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <functional> | |
#include <tuple> | |
#include <type_traits> | |
template<typename T, typename U, typename V> | |
class ReduceOperator { | |
T _init; | |
U _apply; | |
V _chain; | |
public: | |
template<typename X, typename Y, typename Z> | |
constexpr ReduceOperator(X&& init, Y&& apply, Z&& chain) : | |
_init{std::forward<X>(init)}, | |
_apply{std::forward<Y>(apply)}, | |
_chain{std::forward<Z>(chain)} | |
{} | |
template<typename X, typename Y> | |
class ReduceOperatorImpl { | |
const ReduceOperator& _op; | |
const X& _value; | |
Y _acc; | |
public: | |
constexpr ReduceOperatorImpl(const ReduceOperator& op, const X& value) : | |
_op{op}, | |
_value{value}, | |
_acc{op._init()} | |
{} | |
constexpr operator Y() { return _acc; } | |
template<typename Z> | |
constexpr ReduceOperatorImpl& operator>(const Z& value) { | |
_acc = _op._chain(_acc, _op._apply(_value, value)); | |
return *this; | |
} | |
template<typename Z> | |
constexpr ReduceOperatorImpl& operator,(const Z& value) { | |
_acc = _op._chain(_acc, _op._apply(_value, value)); | |
return *this; | |
} | |
}; | |
template<typename X> | |
friend constexpr auto operator<(const X& value, const ReduceOperator& op) { | |
return ReduceOperatorImpl<X, decltype(op._init())>{op, value}; | |
} | |
}; | |
template<typename T, typename U, typename V> | |
constexpr auto make_reduce_operator(T&& init, U&& apply, V&& chain) { | |
return ReduceOperator<std::decay_t<T>, std::decay_t<U>, std::decay_t<V>>{ | |
std::forward<T>(init), | |
std::forward<U>(apply), | |
std::forward<V>(chain) | |
}; | |
} | |
// Proof of concept, <in> operator: | |
constexpr auto in = make_reduce_operator( | |
[]() constexpr { return false; }, | |
[](auto&& l, auto&& r) constexpr { return l == r; }, | |
[](auto&& a, auto&& r) constexpr { return a || r; } | |
); | |
// Usage: | |
// 0 <in> 1, 2, 3 // returns: false | |
// 1 <in> 1, 2, 3 // returns: true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment