constexpr な fusion::invoke
まぁそんな感じの処理です。
関数の引数を Tuple で渡して評価します。
[ソース]
#define SPROUT_CONFIG_SUPPORT_TEMPORARY_CONTAINER_ITERATION #include <sprout/tuple.hpp> template<std::size_t... Indices> struct index_tuple{}; template< std::size_t Start, std::size_t Finish, std::size_t Step = 1, typename Acc = index_tuple<>, bool Break = (Start >= Finish) > struct index_range{ typedef Acc type; }; template< std::size_t Start, std::size_t Finish, std::size_t Step, std::size_t... Indices > struct index_range<Start, Finish, Step, index_tuple<Indices...>, false> : index_range<Start + Step, Finish, Step, index_tuple<Indices..., Start>> {}; namespace aliases{ template<typename T> using remove_reference = typename std::remove_reference<T>::type; template<std::size_t Index, typename T> using tuple_element = typename sprout::tuple_element<Index, T>::type; template<std::size_t N> using index_range = typename ::index_range<0, N>::type; } // namespace aliases template<typename F, typename Tuple, std::size_t... Indices> constexpr auto invoke_impl(F f, Tuple&& t, index_tuple<Indices...>) ->decltype(f(sprout::tuples::get<Indices>(sprout::forward<Tuple>(t))...)){ return f(sprout::tuples::get<Indices>(sprout::forward<Tuple>(t))...); } template<typename F, typename Tuple, typename IndexRange = aliases::index_range< sprout::tuple_size<aliases::remove_reference<Tuple>>{} > > constexpr auto invoke(F f, Tuple&& t) ->decltype(invoke_impl(f, sprout::forward<Tuple>(t), IndexRange())){ return invoke_impl(f, sprout::forward<Tuple>(t), IndexRange()); } #include <sprout/string.hpp> constexpr int minus(int a, int b){ return a - b; } struct plus{ template<typename T, typename U> constexpr auto operator ()(T&& t, U&& u) const ->decltype(std::forward<T>(t) + std::forward<U>(u)){ return std::forward<T>(t) + std::forward<U>(u); } }; int main(){ static_assert(invoke(&minus, sprout::make_tuple(5, 2)) == 3, ""); constexpr auto t = sprout::make_tuple( sprout::to_string("homu"), sprout::to_string("mado") ); static_assert(invoke(plus{}, t) == "homumado", ""); return 0; }
標準ライブラリの Tuple が constexpr ではないので、Sprout.Tuple を使用しています。