/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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. */ #pragma once #include <functional> #include <tuple> #include <utility> #include <folly/Traits.h> #include <folly/Utility.h> #include <folly/functional/Invoke.h> namespace folly { ////////////////////////////////////////////////////////////////////// /** * Helper to generate an index sequence from a tuple like type */ index_sequence_for_tuple; namespace detail { namespace apply_tuple { namespace adl { get; template <std::size_t I> struct invoke_get_fn { … }; } // namespace adl template < typename Tuple, std::size_t... Indices, typename ReturnTuple = std::tuple< decltype(adl::invoke_get_fn<Indices>{ … } } // namespace apply_tuple } // namespace detail struct ApplyInvoke { … }; ////////////////////////////////////////////////////////////////////// /* using override */ apply; /** * Get a tuple of references from the passed tuple, forwarding will be applied * on the individual types of the tuple based on the value category of the * passed tuple * * For example * * forward_tuple(std::make_tuple(1, 2)) * * Returns a std::tuple<int&&, int&&>, * * auto tuple = std::make_tuple(1, 2); * forward_tuple(tuple) * * Returns a std::tuple<int&, int&> */ template <typename Tuple> auto forward_tuple(Tuple&& tuple) noexcept -> decltype(detail::apply_tuple::forward_tuple( std::declval<Tuple>(), std::declval< index_sequence_for_tuple<std::remove_reference_t<Tuple>>>())) { … } /** * Mimic the invoke suite of traits for tuple based apply invocation */ apply_result; apply_result_t; is_applicable_v; is_applicable; is_applicable_r_v; is_applicable_r; is_nothrow_applicable_v; is_nothrow_applicable; is_nothrow_applicable_r_v; is_nothrow_applicable_r; namespace detail { namespace apply_tuple { template <class F> class Uncurry { … }; } // 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> { … } ////////////////////////////////////////////////////////////////////// } // namespace folly