1050b064fSChristopher Di Bella // -*- C++ -*- 2050b064fSChristopher Di Bella //===----------------------------------------------------------------------===// 3050b064fSChristopher Di Bella // 4050b064fSChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5050b064fSChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information. 6050b064fSChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7050b064fSChristopher Di Bella // 8050b064fSChristopher Di Bella //===----------------------------------------------------------------------===// 9050b064fSChristopher Di Bella 10050b064fSChristopher Di Bella #ifndef _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H 11050b064fSChristopher Di Bella #define _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H 12050b064fSChristopher Di Bella 13050b064fSChristopher Di Bella #include <__config> 1409e3a360SLouis Dionne #include <__cstddef/size_t.h> 156d6e3289SLouis Dionne #include <__type_traits/enable_if.h> 166d6e3289SLouis Dionne #include <__type_traits/invoke.h> 176d6e3289SLouis Dionne #include <__type_traits/is_constructible.h> 18f599e7a7SLouis Dionne #include <__utility/declval.h> 19f599e7a7SLouis Dionne #include <__utility/forward.h> 206d6e3289SLouis Dionne #include <__utility/integer_sequence.h> 21f599e7a7SLouis Dionne #include <__utility/move.h> 22050b064fSChristopher Di Bella #include <tuple> 23050b064fSChristopher Di Bella 24050b064fSChristopher Di Bella #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 25050b064fSChristopher Di Bella # pragma GCC system_header 26050b064fSChristopher Di Bella #endif 27050b064fSChristopher Di Bella 2892e4d679SNicole Rabjohn _LIBCPP_PUSH_MACROS 2992e4d679SNicole Rabjohn #include <__undef_macros> 3092e4d679SNicole Rabjohn 31050b064fSChristopher Di Bella _LIBCPP_BEGIN_NAMESPACE_STD 32050b064fSChristopher Di Bella 334f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 17 34050b064fSChristopher Di Bella 355a4f177cSPeter Kasting template <class _Op, class _Indices, class... _BoundArgs> 36050b064fSChristopher Di Bella struct __perfect_forward_impl; 37050b064fSChristopher Di Bella 385a4f177cSPeter Kasting template <class _Op, size_t... _Idx, class... _BoundArgs> 395a4f177cSPeter Kasting struct __perfect_forward_impl<_Op, index_sequence<_Idx...>, _BoundArgs...> { 40f599e7a7SLouis Dionne private: 415a4f177cSPeter Kasting tuple<_BoundArgs...> __bound_args_; 42050b064fSChristopher Di Bella 43f599e7a7SLouis Dionne public: 449783f28cSLouis Dionne template <class... _Args, class = enable_if_t< is_constructible_v<tuple<_BoundArgs...>, _Args&&...> >> 4583ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI explicit constexpr __perfect_forward_impl(_Args&&... __bound_args) 4677a00c0dSLouis Dionne : __bound_args_(std::forward<_Args>(__bound_args)...) {} 47050b064fSChristopher Di Bella 4883ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl(__perfect_forward_impl const&) = default; 4983ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl(__perfect_forward_impl&&) = default; 50050b064fSChristopher Di Bella 5183ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl& operator=(__perfect_forward_impl const&) = default; 5283ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI __perfect_forward_impl& operator=(__perfect_forward_impl&&) = default; 53050b064fSChristopher Di Bella 545a4f177cSPeter Kasting template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs&..., _Args...>>> 559783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) & noexcept( 569783f28cSLouis Dionne noexcept(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...))) 579783f28cSLouis Dionne -> decltype(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...)) { 589783f28cSLouis Dionne return _Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...); 599783f28cSLouis Dionne } 60050b064fSChristopher Di Bella 615a4f177cSPeter Kasting template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs&..., _Args...>>> 62f599e7a7SLouis Dionne auto operator()(_Args&&...) & = delete; 63050b064fSChristopher Di Bella 645a4f177cSPeter Kasting template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs const&..., _Args...>>> 659783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const& noexcept( 669783f28cSLouis Dionne noexcept(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...))) 679783f28cSLouis Dionne -> decltype(_Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...)) { 689783f28cSLouis Dionne return _Op()(std::get<_Idx>(__bound_args_)..., std::forward<_Args>(__args)...); 699783f28cSLouis Dionne } 70050b064fSChristopher Di Bella 715a4f177cSPeter Kasting template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs const&..., _Args...>>> 72f599e7a7SLouis Dionne auto operator()(_Args&&...) const& = delete; 73f599e7a7SLouis Dionne 745a4f177cSPeter Kasting template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs..., _Args...>>> 759783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) && noexcept( 769783f28cSLouis Dionne noexcept(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...))) 779783f28cSLouis Dionne -> decltype(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...)) { 789783f28cSLouis Dionne return _Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...); 799783f28cSLouis Dionne } 80f599e7a7SLouis Dionne 815a4f177cSPeter Kasting template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs..., _Args...>>> 82f599e7a7SLouis Dionne auto operator()(_Args&&...) && = delete; 83f599e7a7SLouis Dionne 845a4f177cSPeter Kasting template <class... _Args, class = enable_if_t<is_invocable_v<_Op, _BoundArgs const..., _Args...>>> 859783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Args&&... __args) const&& noexcept( 869783f28cSLouis Dionne noexcept(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...))) 879783f28cSLouis Dionne -> decltype(_Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...)) { 889783f28cSLouis Dionne return _Op()(std::get<_Idx>(std::move(__bound_args_))..., std::forward<_Args>(__args)...); 899783f28cSLouis Dionne } 90f599e7a7SLouis Dionne 915a4f177cSPeter Kasting template <class... _Args, class = enable_if_t<!is_invocable_v<_Op, _BoundArgs const..., _Args...>>> 92f599e7a7SLouis Dionne auto operator()(_Args&&...) const&& = delete; 93050b064fSChristopher Di Bella }; 94050b064fSChristopher Di Bella 95f599e7a7SLouis Dionne // __perfect_forward implements a perfect-forwarding call wrapper as explained in [func.require]. 96050b064fSChristopher Di Bella template <class _Op, class... _Args> 97*f6958523SNikolas Klauser using __perfect_forward _LIBCPP_NODEBUG = __perfect_forward_impl<_Op, index_sequence_for<_Args...>, _Args...>; 98050b064fSChristopher Di Bella 994f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 17 100050b064fSChristopher Di Bella 101050b064fSChristopher Di Bella _LIBCPP_END_NAMESPACE_STD 102050b064fSChristopher Di Bella 10392e4d679SNicole Rabjohn _LIBCPP_POP_MACROS 10492e4d679SNicole Rabjohn 105050b064fSChristopher Di Bella #endif // _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H 106