106 lines · c
1// -*- C++ -*-2//===----------------------------------------------------------------------===//3//4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H11#define _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H12 13#include <__config>14#include <__cstddef/size_t.h>15#include <__type_traits/enable_if.h>16#include <__type_traits/invoke.h>17#include <__type_traits/is_constructible.h>18#include <__utility/declval.h>19#include <__utility/forward.h>20#include <__utility/integer_sequence.h>21#include <__utility/move.h>22#include <tuple>23 24#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)25# pragma GCC system_header26#endif27 28_LIBCPP_PUSH_MACROS29#include <__undef_macros>30 31_LIBCPP_BEGIN_NAMESPACE_STD32 33#if _LIBCPP_STD_VER >= 1734 35template <class _Op, class _Indices, class... _BoundArgs>36struct __perfect_forward_impl;37 38template <class _Op, size_t... _Idx, class... _BoundArgs>39struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> {40private:41 tuple<_BoundArgs...> __bound_args_;42 43public:44 template <class... _Args, class = enable_if_t< is_constructible_v<tuple<_BoundArgs...>, _Args&&...> >>45 _LIBCPP_HIDE_FROM_ABI explicit constexpr __perfect_forward_impl(_Args&&... __bound_args)46 : __bound_args_(std::forward<_Args>(__bound_args)...) {}47 48 _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl(__perfect_forward_impl const&) = default;49 _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl(__perfect_forward_impl&&) = default;50 51 _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl& operator=(__perfect_forward_impl const&) = default;52 _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl& operator=(__perfect_forward_impl&&) = default;53 54 template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs&..., _Args...>>>55 _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) & noexcept(56 noexcept(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...)))57 -> decltype(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...)) {58 return _Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...);59 }60 61 template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs&..., _Args...>>>62 auto operator()(_Args&&...) & = delete;63 64 template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs const&..., _Args...>>>65 _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const& noexcept(66 noexcept(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...)))67 -> decltype(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...)) {68 return _Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...);69 }70 71 template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs const&..., _Args...>>>72 auto operator()(_Args&&...) const& = delete;73 74 template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs..., _Args...>>>75 _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) && noexcept(76 noexcept(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...)))77 -> decltype(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...)) {78 return _Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...);79 }80 81 template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs..., _Args...>>>82 auto operator()(_Args&&...) && = delete;83 84 template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs const..., _Args...>>>85 _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const&& noexcept(86 noexcept(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...)))87 -> decltype(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...)) {88 return _Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...);89 }90 91 template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs const..., _Args...>>>92 auto operator()(_Args&&...) const&& = delete;93};94 95// __perfect_forward implements a perfect-forwarding call wrapper as explained in [func.require].96template <class _Op, class... _Args>97using __perfect_forward _LIBCPP_NODEBUG = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>;98 99#endif // _LIBCPP_STD_VER >= 17100 101_LIBCPP_END_NAMESPACE_STD102 103_LIBCPP_POP_MACROS104 105#endif // _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H106