xref: /llvm-project/libcxx/include/__functional/perfect_forward.h (revision f69585235ec85d54e0f3fc41b2d5700430907f99)
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