From: Sven Over Date: Thu, 11 Aug 2016 08:40:38 +0000 (-0700) Subject: Let applyTuple accept any number of tuples X-Git-Tag: v2016.08.15.00~15 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=efc54c28e4922cb8f1d4904dd9674c4c9a3b825c;p=folly.git Let applyTuple accept any number of tuples Summary: Instead of passing exactly one tuple of arguments to applyTuple, this diff allows to pass any number (zero or more) of tuples. This can be very handy when piecing together arguments for a function call. Reviewed By: yfeldblum Differential Revision: D3681499 fbshipit-source-id: a75a448636759f71db8d303e9dccada5b559af54 --- diff --git a/folly/ApplyTuple.h b/folly/ApplyTuple.h index 3a8e14ee..0288f567 100644 --- a/folly/ApplyTuple.h +++ b/folly/ApplyTuple.h @@ -28,6 +28,7 @@ #pragma once #include +#include #include namespace folly { @@ -46,9 +47,17 @@ struct MakeIndexSequence : MakeIndexSequence {}; template struct MakeIndexSequence<0, Is...> : IndexSequence {}; -template -using MakeIndexSequenceFromTuple = - MakeIndexSequence::type>::value>; +inline constexpr std::size_t sum() { + return 0; +} +template +inline constexpr std::size_t sum(std::size_t v1, Args... vs) { + return v1 + sum(vs...); +} + +template +using MakeIndexSequenceFromTuple = MakeIndexSequence::type>::value...)>; // This is to allow using this with pointers to member functions, // where the first argument in the tuple will be the this pointer. @@ -68,21 +77,42 @@ inline constexpr auto call(F&& f, Tuple&& t, IndexSequence) return std::forward(f)(std::get(std::forward(t))...); } +template +inline constexpr auto forwardTuple(Tuple&& t, IndexSequence) + -> decltype( + std::forward_as_tuple(std::get(std::forward(t))...)) { + return std::forward_as_tuple(std::get(std::forward(t))...); +} + } // namespace apply_tuple } // namespace detail ////////////////////////////////////////////////////////////////////// -template -inline constexpr auto applyTuple(F&& f, Tuple&& t) +/** + * Invoke a callable object with a set of arguments passed as a tuple, or a + * series of tuples + * + * Example: the following lines are equivalent + * func(1, 2, 3, "foo"); + * applyTuple(func, std::make_tuple(1, 2, 3, "foo")); + * applyTuple(func, std::make_tuple(1, 2), std::make_tuple(3, "foo")); + */ + +template +inline constexpr auto applyTuple(F&& f, Tuples&&... t) -> decltype(detail::apply_tuple::call( detail::apply_tuple::makeCallable(std::forward(f)), - std::forward(t), - detail::apply_tuple::MakeIndexSequenceFromTuple{})) { + std::tuple_cat(detail::apply_tuple::forwardTuple( + std::forward(t), + detail::apply_tuple::MakeIndexSequenceFromTuple{})...), + detail::apply_tuple::MakeIndexSequenceFromTuple{})) { return detail::apply_tuple::call( detail::apply_tuple::makeCallable(std::forward(f)), - std::forward(t), - detail::apply_tuple::MakeIndexSequenceFromTuple{}); + std::tuple_cat(detail::apply_tuple::forwardTuple( + std::forward(t), + detail::apply_tuple::MakeIndexSequenceFromTuple{})...), + detail::apply_tuple::MakeIndexSequenceFromTuple{}); } ////////////////////////////////////////////////////////////////////// diff --git a/folly/test/ApplyTupleTest.cpp b/folly/test/ApplyTupleTest.cpp index 92ebac3f..e29c9914 100644 --- a/folly/test/ApplyTupleTest.cpp +++ b/folly/test/ApplyTupleTest.cpp @@ -287,3 +287,30 @@ TEST(ApplyTuple, Pair) { EXPECT_EQ(folly::applyTuple(add, std::pair{1200, 34}), 1234); } + +TEST(ApplyTuple, MultipleTuples) { + auto add = [](int x, int y, int z) { return x * 100 + y * 10 + z; }; + + EXPECT_EQ(123, folly::applyTuple(add, std::make_tuple(1, 2, 3))); + EXPECT_EQ( + 123, folly::applyTuple(add, std::make_tuple(1, 2, 3), std::make_tuple())); + EXPECT_EQ( + 123, folly::applyTuple(add, std::make_tuple(1, 2), std::make_tuple(3))); + EXPECT_EQ( + 123, folly::applyTuple(add, std::make_tuple(1), std::make_tuple(2, 3))); + EXPECT_EQ( + 123, folly::applyTuple(add, std::make_tuple(), std::make_tuple(1, 2, 3))); + + EXPECT_EQ( + 123, + folly::applyTuple( + add, std::make_tuple(1, 2, 3), std::make_tuple(), std::make_tuple())); + EXPECT_EQ( + 123, + folly::applyTuple( + add, std::make_tuple(1), std::make_tuple(2), std::make_tuple(3))); + EXPECT_EQ( + 123, + folly::applyTuple( + add, std::make_tuple(1), std::make_tuple(), std::make_tuple(2, 3))); +}