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_REFERENCE_WRAPPER_H
11#define _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H
12
13#include <__config>
14#include <__functional/invoke.h>
15#include <__functional/weak_result_type.h>
16#include <__memory/addressof.h>
17#include <__type_traits/enable_if.h>
18#include <__type_traits/remove_cvref.h>
19#include <__utility/declval.h>
20#include <__utility/forward.h>
21
22#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23#  pragma GCC system_header
24#endif
25
26_LIBCPP_BEGIN_NAMESPACE_STD
27
28template <class _Tp>
29class _LIBCPP_TEMPLATE_VIS reference_wrapper : public __weak_result_type<_Tp> {
30public:
31  // types
32  typedef _Tp type;
33
34private:
35  type* __f_;
36
37  static void __fun(_Tp&) _NOEXCEPT;
38  static void __fun(_Tp&&) = delete;
39
40public:
41  template <
42      class _Up,
43      class = __enable_if_t<!__is_same_uncvref<_Up, reference_wrapper>::value, decltype(__fun(std::declval<_Up>())) > >
44  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper(_Up&& __u)
45      _NOEXCEPT_(noexcept(__fun(std::declval<_Up>()))) {
46    type& __f = static_cast<_Up&&>(__u);
47    __f_      = std::addressof(__f);
48  }
49
50  // access
51  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator type&() const _NOEXCEPT { return *__f_; }
52  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 type& get() const _NOEXCEPT { return *__f_; }
53
54  // invoke
55  template <class... _ArgTypes>
56  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __invoke_of<type&, _ArgTypes...>::type
57  operator()(_ArgTypes&&... __args) const
58#if _LIBCPP_STD_VER >= 17
59      // Since is_nothrow_invocable requires C++17 LWG3764 is not backported
60      // to earlier versions.
61      noexcept(is_nothrow_invocable_v<_Tp&, _ArgTypes...>)
62#endif
63  {
64    return std::__invoke(get(), std::forward<_ArgTypes>(__args)...);
65  }
66};
67
68#if _LIBCPP_STD_VER >= 17
69template <class _Tp>
70reference_wrapper(_Tp&) -> reference_wrapper<_Tp>;
71#endif
72
73template <class _Tp>
74inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp> ref(_Tp& __t) _NOEXCEPT {
75  return reference_wrapper<_Tp>(__t);
76}
77
78template <class _Tp>
79inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp>
80ref(reference_wrapper<_Tp> __t) _NOEXCEPT {
81  return __t;
82}
83
84template <class _Tp>
85inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp> cref(const _Tp& __t) _NOEXCEPT {
86  return reference_wrapper<const _Tp>(__t);
87}
88
89template <class _Tp>
90inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp>
91cref(reference_wrapper<_Tp> __t) _NOEXCEPT {
92  return __t;
93}
94
95template <class _Tp>
96void ref(const _Tp&&) = delete;
97template <class _Tp>
98void cref(const _Tp&&) = delete;
99
100_LIBCPP_END_NAMESPACE_STD
101
102#endif // _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H
103