+++ /dev/null
-/*
- * Copyright 2017 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Defines a function folly::applyTuple, which takes a function and a
- * std::tuple of arguments and calls the function with those
- * arguments.
- *
- * Example:
- *
- * int x = folly::applyTuple(std::plus<int>(), std::make_tuple(12, 12));
- * ASSERT(x == 24);
- */
-
-#pragma once
-
-#include <functional>
-#include <tuple>
-#include <utility>
-
-#include <folly/Utility.h>
-
-namespace folly {
-
-//////////////////////////////////////////////////////////////////////
-
-namespace detail {
-namespace apply_tuple {
-
-inline constexpr std::size_t sum() {
- return 0;
-}
-template <typename... Args>
-inline constexpr std::size_t sum(std::size_t v1, Args... vs) {
- return v1 + sum(vs...);
-}
-
-template <typename... Tuples>
-struct TupleSizeSum {
- static constexpr auto value = sum(std::tuple_size<Tuples>::value...);
-};
-
-template <typename... Tuples>
-using MakeIndexSequenceFromTuple = folly::make_index_sequence<
- TupleSizeSum<typename std::decay<Tuples>::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.
-template <class F>
-inline constexpr F&& makeCallable(F&& f) {
- return std::forward<F>(f);
-}
-template <class M, class C>
-inline constexpr auto makeCallable(M(C::*d)) -> decltype(std::mem_fn(d)) {
- return std::mem_fn(d);
-}
-
-template <class F, class Tuple, std::size_t... Indexes>
-inline constexpr auto call(F&& f, Tuple&& t, folly::index_sequence<Indexes...>)
- -> decltype(
- std::forward<F>(f)(std::get<Indexes>(std::forward<Tuple>(t))...)) {
- return std::forward<F>(f)(std::get<Indexes>(std::forward<Tuple>(t))...);
-}
-
-template <class Tuple, std::size_t... Indexes>
-inline constexpr auto forwardTuple(Tuple&& t, folly::index_sequence<Indexes...>)
- -> decltype(
- std::forward_as_tuple(std::get<Indexes>(std::forward<Tuple>(t))...)) {
- return std::forward_as_tuple(std::get<Indexes>(std::forward<Tuple>(t))...);
-}
-
-} // namespace apply_tuple
-} // namespace detail
-
-//////////////////////////////////////////////////////////////////////
-
-/**
- * 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 <class F, class... Tuples>
-inline constexpr auto applyTuple(F&& f, Tuples&&... t)
- -> decltype(detail::apply_tuple::call(
- detail::apply_tuple::makeCallable(std::forward<F>(f)),
- std::tuple_cat(detail::apply_tuple::forwardTuple(
- std::forward<Tuples>(t),
- detail::apply_tuple::MakeIndexSequenceFromTuple<Tuples>{})...),
- detail::apply_tuple::MakeIndexSequenceFromTuple<Tuples...>{})) {
- return detail::apply_tuple::call(
- detail::apply_tuple::makeCallable(std::forward<F>(f)),
- std::tuple_cat(detail::apply_tuple::forwardTuple(
- std::forward<Tuples>(t),
- detail::apply_tuple::MakeIndexSequenceFromTuple<Tuples>{})...),
- detail::apply_tuple::MakeIndexSequenceFromTuple<Tuples...>{});
-}
-
-namespace detail {
-namespace apply_tuple {
-
-template <class F>
-class Uncurry {
- public:
- explicit Uncurry(F&& func) : func_(std::move(func)) {}
- explicit Uncurry(const F& func) : func_(func) {}
-
- template <class Tuple>
- auto operator()(Tuple&& tuple) const
- -> decltype(applyTuple(std::declval<F>(), std::forward<Tuple>(tuple))) {
- return applyTuple(func_, std::forward<Tuple>(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<std::tuple<int, int, int>> rows = ...;
- * auto test = [](std::tuple<int, int, int>& 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 <class F>
-auto uncurry(F&& f)
- -> detail::apply_tuple::Uncurry<typename std::decay<F>::type> {
- return detail::apply_tuple::Uncurry<typename std::decay<F>::type>(
- std::forward<F>(f));
-}
-
-//////////////////////////////////////////////////////////////////////
-}