Last active
August 29, 2015 14:22
-
-
Save PkmX/0fa65c755c39b676d79e to your computer and use it in GitHub Desktop.
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> | |
| #include <iostream> | |
| #include <stdexcept> | |
| #include <string> | |
| #include <type_traits> | |
| #include <tuple> | |
| #include <experimental/tuple> | |
| #include <boost/variant.hpp> | |
| namespace std { | |
| using std::experimental::apply; | |
| } | |
| using empty_t = std::tuple<>; | |
| namespace detail { | |
| template<typename T> struct storable_of { using type = T; }; | |
| template<> struct storable_of<void> { using type = empty_t; }; | |
| template<typename T> using storable_of_t = typename storable_of<T>::type; | |
| template<typename Args, typename... F> | |
| struct index_call_result_type { | |
| using type = boost::variant<storable_of_t<decltype(std::apply(std::forward<F>(std::declval<F>()), std::forward<Args>(std::declval<Args>())))>..., empty_t>; | |
| }; | |
| template<typename... T> using index_call_result_type_t = typename index_call_result_type<T...>::type; | |
| template<typename F> | |
| auto make_storable(F&& f) -> std::enable_if_t<std::is_void<decltype(f())>{}, storable_of_t<void>> { | |
| f(); return {}; | |
| } | |
| template<typename F> | |
| auto make_storable(F&& f) -> std::enable_if_t<!std::is_void<decltype(f())>{}, storable_of_t<decltype(f())>> { | |
| return f(); | |
| } | |
| } | |
| template<typename Args> | |
| auto index_call(const std::size_t, Args&&) -> detail::index_call_result_type_t<Args> { | |
| throw std::out_of_range("index_call: out of range"); | |
| } | |
| template<typename Args, typename F, typename... FS> | |
| auto index_call(const std::size_t i, Args&& args, F&& f, FS&&... fs) -> detail::index_call_result_type_t<Args, F, FS...> { | |
| if (i == 0) { | |
| return detail::make_storable([&] { return std::apply(std::forward<F>(f), std::forward<Args>(args)); }); | |
| } else { | |
| return index_call(i - 1, std::forward<Args>(args), std::forward<FS>(fs)...); | |
| } | |
| } | |
| void f1(const int x) { std::cout << "f1: " << x << std::endl; } | |
| void f2(const double x) { std::cout << "f2: " << x << std::endl; } | |
| std::string f3(const int x) { std::cout << "f3: " << x << std::endl; return std::to_string(x + x); } | |
| int main() { | |
| index_call(0, std::make_tuple(42), f1, f2); | |
| index_call(1, std::make_tuple(42), f1, f2); | |
| const auto v1 = index_call(2, std::make_tuple(42), f1, f2, f3); | |
| std::cout << boost::get<std::string>(v1) << std::endl; | |
| const auto v2 = index_call(1, std::make_tuple(), std::bind(f3, 0), [] { std::cout << "lambda" << std::endl; return 42; }); | |
| std::cout << boost::get<int>(v2) << std::endl; | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment