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-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H
11 #define _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H
12 
13 #include <__config>
14 #include <tuple>
15 #include <type_traits>
16 #include <utility>
17 
18 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
19 #pragma GCC system_header
20 #endif
21 
22 _LIBCPP_BEGIN_NAMESPACE_STD
23 
24 #if _LIBCPP_STD_VER > 14
25 
26 template<class _Op, class _Tuple,
27          class _Idxs = typename __make_tuple_indices<tuple_size<_Tuple>::value>::type>
28 struct __perfect_forward_impl;
29 
30 template<class _Op, class... _Bound, size_t... _Idxs>
31 struct __perfect_forward_impl<_Op, __tuple_types<_Bound...>, __tuple_indices<_Idxs...>>
32 {
33     tuple<_Bound...> __bound_;
34 
35     template<class... _Args>
36     _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) &
37     noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...)))
38     -> decltype(      _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...))
39     {return           _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...);}
40 
41     template<class... _Args>
42     _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const&
43     noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...)))
44     -> decltype(      _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...))
45     {return           _Op::__call(_VSTD::get<_Idxs>(__bound_)..., _VSTD::forward<_Args>(__args)...);}
46 
47     template<class... _Args>
48     _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) &&
49     noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
50                                   _VSTD::forward<_Args>(__args)...)))
51     -> decltype(      _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
52                                   _VSTD::forward<_Args>(__args)...))
53     {return           _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
54                                   _VSTD::forward<_Args>(__args)...);}
55 
56     template<class... _Args>
57     _LIBCPP_INLINE_VISIBILITY constexpr auto operator()(_Args&&... __args) const&&
58     noexcept(noexcept(_Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
59                                   _VSTD::forward<_Args>(__args)...)))
60     -> decltype(      _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
61                                   _VSTD::forward<_Args>(__args)...))
62     {return           _Op::__call(_VSTD::get<_Idxs>(_VSTD::move(__bound_))...,
63                                   _VSTD::forward<_Args>(__args)...);}
64 
65     template<class _Fn = typename tuple_element<0, tuple<_Bound...>>::type,
66              class = _EnableIf<is_copy_constructible_v<_Fn>>>
67     constexpr __perfect_forward_impl(__perfect_forward_impl const& __other)
68         : __bound_(__other.__bound_) {}
69 
70     template<class _Fn = typename tuple_element<0, tuple<_Bound...>>::type,
71              class = _EnableIf<is_move_constructible_v<_Fn>>>
72     constexpr __perfect_forward_impl(__perfect_forward_impl && __other)
73         : __bound_(_VSTD::move(__other.__bound_)) {}
74 
75     template<class... _BoundArgs>
76     explicit constexpr __perfect_forward_impl(_BoundArgs&&... __bound) :
77         __bound_(_VSTD::forward<_BoundArgs>(__bound)...) { }
78 };
79 
80 template<class _Op, class... _Args>
81 using __perfect_forward =
82     __perfect_forward_impl<_Op, __tuple_types<decay_t<_Args>...>>;
83 
84 #endif // _LIBCPP_STD_VER > 14
85 
86 _LIBCPP_END_NAMESPACE_STD
87 
88 #endif // _LIBCPP___FUNCTIONAL_PERFECT_FORWARD_H
89