X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2FApplyTuple.h;h=cce6fec07d6e3e23bf0e6a574f8ac352535953db;hp=41ac5337dec4df1366b72ebc4f88de2967011816;hb=f975d3c54800b7065985e5e548ce1d91fef4926c;hpb=ed8c80a0e0988e4ce687f51ca832a00e4a6b7930 diff --git a/folly/ApplyTuple.h b/folly/ApplyTuple.h index 41ac5337..cce6fec0 100644 --- a/folly/ApplyTuple.h +++ b/folly/ApplyTuple.h @@ -31,6 +31,8 @@ #include #include +#include + namespace folly { ////////////////////////////////////////////////////////////////////// @@ -38,15 +40,6 @@ namespace folly { namespace detail { namespace apply_tuple { -template -struct IndexSequence {}; - -template -struct MakeIndexSequence : MakeIndexSequence {}; - -template -struct MakeIndexSequence<0, Is...> : IndexSequence {}; - inline constexpr std::size_t sum() { return 0; } @@ -61,7 +54,7 @@ struct TupleSizeSum { }; template -using MakeIndexSequenceFromTuple = MakeIndexSequence< +using MakeIndexSequenceFromTuple = folly::make_index_sequence< TupleSizeSum::type...>::value>; // This is to allow using this with pointers to member functions, @@ -76,14 +69,14 @@ inline constexpr auto makeCallable(M(C::*d)) -> decltype(std::mem_fn(d)) { } template -inline constexpr auto call(F&& f, Tuple&& t, IndexSequence) +inline constexpr auto call(F&& f, Tuple&& t, folly::index_sequence) -> decltype( std::forward(f)(std::get(std::forward(t))...)) { return std::forward(f)(std::get(std::forward(t))...); } template -inline constexpr auto forwardTuple(Tuple&& t, IndexSequence) +inline constexpr auto forwardTuple(Tuple&& t, folly::index_sequence) -> decltype( std::forward_as_tuple(std::get(std::forward(t))...)) { return std::forward_as_tuple(std::get(std::forward(t))...); @@ -120,5 +113,52 @@ inline constexpr auto applyTuple(F&& f, Tuples&&... t) detail::apply_tuple::MakeIndexSequenceFromTuple{}); } +namespace detail { +namespace apply_tuple { + +template +class Uncurry { + public: + explicit Uncurry(F&& func) : func_(std::move(func)) {} + explicit Uncurry(const F& func) : func_(func) {} + + template + auto operator()(Tuple&& tuple) const + -> decltype(applyTuple(std::declval(), std::forward(tuple))) { + return applyTuple(func_, std::forward(tuple)); + } + + private: + F func_; +}; +} // namespace apply_tuple +} // namespace detail + +/** + * Wraps a function taking N arguments into a function which accepts a tuple of + * N arguments. Note: This function will also accept an std::pair if N == 2. + * + * For example, given the below code: + * + * std::vector> rows = ...; + * auto test = [](std::tuple& row) { + * return std::get<0>(row) * std::get<1>(row) * std::get<2>(row) == 24; + * }; + * auto found = std::find_if(rows.begin(), rows.end(), test); + * + * + * 'test' could be rewritten as: + * + * auto test = + * folly::uncurry([](int a, int b, int c) { return a * b * c == 24; }); + * + */ +template +auto uncurry(F&& f) + -> detail::apply_tuple::Uncurry::type> { + return detail::apply_tuple::Uncurry::type>( + std::forward(f)); +} + ////////////////////////////////////////////////////////////////////// }