Last active
November 16, 2018 15:41
-
-
Save jzrake/8ae0b0317f6c3ce2a798d597f3f4bf29 to your computer and use it in GitHub Desktop.
An proof-of-concept for operator chaining in constructing algorithms
This file contains hidden or 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> | |
// ============================================================================ | |
namespace detail | |
{ | |
template <typename T> | |
struct function_traits : public function_traits<decltype(&T::operator())> | |
{ | |
}; | |
template <typename ClassType, typename ReturnType, typename... Args> | |
struct function_traits<ReturnType(ClassType::*)(Args...) const> | |
{ | |
typedef ReturnType result_type; | |
enum { arity = sizeof...(Args) }; | |
template <size_t i> struct arg | |
{ | |
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type; | |
}; | |
}; | |
} | |
template<typename Lambda> | |
auto make_mapping(Lambda f); | |
// ============================================================================ | |
template<typename A, typename B> | |
struct mapping | |
{ | |
mapping(std::function<B(A)> f) : f(f) | |
{ | |
} | |
B operator()(A a) const | |
{ | |
return f(a); | |
} | |
template<typename Z> | |
auto operator()(mapping<Z, A> other) const | |
{ | |
return mapping<Z, B> ([g=f, h=other.f] (A a) { return g(h(a)); }); | |
} | |
template<typename C> | |
auto operator|(mapping<B, C> other) const | |
{ | |
return mapping<A, C> ([g=f, h=other.f] (A a) { return h(g(a)); }); | |
} | |
template<typename BB> | |
auto operator+(mapping<A, BB> other) const | |
{ | |
return mapping<A, decltype(B() + BB())> ([g=f, h=other.f] (A a) { return g(a) + h(a); }); | |
} | |
template<typename BB> | |
auto operator-(mapping<A, BB> other) const | |
{ | |
return mapping<A, decltype(B() - BB())> ([g=f, h=other.f] (A a) { return g(a) - h(a); }); | |
} | |
template<typename BB> | |
auto operator*(mapping<A, BB> other) const | |
{ | |
return mapping<A, decltype(B() * BB())> ([g=f, h=other.f] (A a) { return g(a) * h(a); }); | |
} | |
template<typename BB> | |
auto operator/(mapping<A, BB> other) const | |
{ | |
return mapping<A, decltype(B() / BB())> ([g=f, h=other.f] (A a) { return g(a) / h(a); }); | |
} | |
template<typename BB> | |
auto operator+(BB other) const | |
{ | |
return mapping<A, decltype(B() + BB())> ([g=f, h=other] (A a) { return g(a) + h; }); | |
} | |
template<typename BB> | |
auto operator-(BB other) const | |
{ | |
return mapping<A, decltype(B() - BB())> ([g=f, h=other] (A a) { return g(a) - h; }); | |
} | |
template<typename BB> | |
auto operator*(BB other) const | |
{ | |
return mapping<A, decltype(B() * BB())> ([g=f, h=other] (A a) { return g(a) * h; }); | |
} | |
template<typename BB> | |
auto operator/(BB other) const | |
{ | |
return mapping<A, decltype(B() / BB())> ([g=f, h=other] (A a) { return g(a) / h; }); | |
} | |
template<typename G> auto operator()(G other) const { return operator()(make_mapping(other)); } | |
template<typename G> auto operator| (G other) const { return operator| (make_mapping(other)); } | |
std::function<B(A)> f; | |
}; | |
// ============================================================================ | |
template<typename Lambda> | |
auto make_mapping(Lambda f) | |
{ | |
using A = typename detail::function_traits<Lambda>::template arg<0>::type; | |
using B = typename detail::function_traits<Lambda>::result_type; | |
return mapping<A, B>(f); | |
} | |
// ============================================================================ | |
template<typename A, typename B> | |
auto tack(mapping<A, B> F) | |
{ | |
return mapping<A, std::tuple<A, B>>([f=F.f] (A i) { return std::make_tuple(i, f(i)); }); | |
} | |
// ============================================================================ | |
#include <iostream> | |
int main() | |
{ | |
auto f = make_mapping([] (int i) { return i; }); | |
auto g = f | make_mapping([] (int i) { return i; }); | |
auto h = f + make_mapping([] (int i) { return i; }); | |
std::cout << h(1) << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment