Last active
November 21, 2019 00:25
-
-
Save talybin/d380f52e7dc385fde3abdc730edd9b05 to your computer and use it in GitHub Desktop.
A scetch. Needs optimization.
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 <iostream> | |
| #include <functional> | |
| #include <tuple> | |
| #include <type_traits> | |
| template <class T> | |
| struct fn_signature | |
| : fn_signature<decltype(std::function(std::declval<T>()))> | |
| { }; | |
| template <class T> | |
| struct fn_signature<std::function<T>> : fn_signature<T> | |
| { }; | |
| template <class R, class... Args> | |
| struct fn_signature<R(Args...)> | |
| { | |
| using return_type = R; | |
| using type = R(Args...); | |
| }; | |
| template <class F> | |
| using ret_t = typename fn_signature<F>::return_type; | |
| template <class F, class... Ts> | |
| struct check_fn : std::true_type { }; | |
| template <class F, class T, class... Ts> | |
| struct check_fn<F, T, Ts...> : check_fn<F, Ts...> { }; | |
| template <class F, class T> | |
| //struct check_fn<F, T> : std::is_invocable<F, ret_t<T>> { }; | |
| struct check_fn<F, T> : std::conditional_t< | |
| std::is_same_v<void, ret_t<T>>, | |
| std::true_type, | |
| std::is_invocable<F, ret_t<T>> > { }; | |
| template <class... Ts> | |
| struct promise | |
| { | |
| promise() = default; | |
| promise(std::tuple<Ts...>&& t) | |
| : holder_(std::move(t)) | |
| { } | |
| template <class F> | |
| promise<Ts..., F> then(F&& fn) const && { | |
| static_assert(check_fn<F, Ts...>::value, | |
| "F must accept previous function return value or do not accept anything"); | |
| return { | |
| std::tuple_cat( | |
| std::move(holder_), | |
| std::tuple<F>(std::forward<F>(fn))) | |
| }; | |
| } | |
| void run() { | |
| if constexpr (sizeof...(Ts) > 0) | |
| run_impl(std::in_place_index<sizeof...(Ts)-1>); | |
| } | |
| private: | |
| template <size_t N> | |
| decltype(auto) run_impl(std::in_place_index_t<N>) | |
| { | |
| using Prev = std::tuple_element_t<N-1, std::tuple<Ts...>>; | |
| if constexpr (std::is_same_v<void, ret_t<Prev>>) { | |
| run_impl(std::in_place_index<N-1>); | |
| return std::get<N>(holder_)(); | |
| } | |
| else return std::get<N>(holder_)( | |
| run_impl(std::in_place_index<N-1>)); | |
| } | |
| decltype(auto) run_impl(std::in_place_index_t<0>) { | |
| return std::get<0>(holder_)(); | |
| } | |
| std::tuple<Ts...> holder_; | |
| }; | |
| int main() | |
| { | |
| auto p = promise<>() | |
| .then([]() { | |
| std::cout << "1\n"; | |
| return 2; | |
| }) | |
| .then([](int x) { | |
| std::cout << x << '\n'; | |
| }) | |
| .then([]() { | |
| std::cout << "taking void\n"; | |
| }) | |
| ; | |
| p.run(); | |
| /* | |
| auto x = []() { | |
| }; | |
| auto y = [](void) { | |
| }; | |
| //y(x()); | |
| auto z = y(); | |
| */ | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment