1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef _LIBCPP___FUNCTIONAL_FUNCTION_REF_COMMON_H
10#define _LIBCPP___FUNCTIONAL_FUNCTION_REF_COMMON_H
11
12#include <__config>
13#include <__type_traits/invoke.h>
14#include <__type_traits/is_const.h>
15#include <__type_traits/is_function.h>
16#include <__type_traits/is_object.h>
17#include <__type_traits/is_reference.h>
18#include <__type_traits/is_trivially_constructible.h>
19#include <__type_traits/is_trivially_destructible.h>
20#include <__type_traits/remove_cv.h>
21#include <__type_traits/remove_pointer.h>
22#include <__utility/constant_wrapper.h>
23#include <__utility/declval.h>
24
25#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26# pragma GCC system_header
27#endif
28
29_LIBCPP_BEGIN_NAMESPACE_STD
30
31#if _LIBCPP_STD_VER >= 26
32
33template <class...>
34class function_ref;
35
36template <class _Fn1, class _Fn2>
37struct __is_convertible_from_specialization : false_type {};
38
39union __function_ref_storage {
40 void* __obj_ptr_;
41 void (*__fn_ptr_)();
42
43 _LIBCPP_HIDE_FROM_ABI constexpr explicit __function_ref_storage() noexcept : __obj_ptr_(nullptr) {}
44
45 template <class _Tp>
46 _LIBCPP_HIDE_FROM_ABI constexpr explicit __function_ref_storage(_Tp* __ptr) noexcept {
47 if constexpr (is_object_v<_Tp>) {
48 __obj_ptr_ = const_cast<remove_cv_t<_Tp>*>(__ptr);
49 } else {
50 static_assert(is_function_v<_Tp>);
51 __fn_ptr_ = reinterpret_cast<void (*)()>(__ptr);
52 }
53 }
54
55 template <class _Tp>
56 _LIBCPP_HIDE_FROM_ABI static constexpr auto __get(__function_ref_storage __storage) {
57 if constexpr (is_object_v<_Tp>) {
58 return static_cast<_Tp*>(__storage.__obj_ptr_);
59 } else {
60 static_assert(is_function_v<_Tp>);
61 return reinterpret_cast<_Tp*>(__storage.__fn_ptr_);
62 }
63 }
64};
65
66template <class _Fp, class _Tp>
67struct __function_ref_bind {};
68
69// F is of the form R(*)(G, A...) noexcept(E) for a type G.
70template <bool _Noexcept, class _Tp, class _Rp, class _Gp, class... _ArgTypes>
71struct __function_ref_bind<_Rp (*)(_Gp, _ArgTypes...) noexcept(_Noexcept), _Tp> {
72 using type _LIBCPP_NODEBUG = _Rp(_ArgTypes...) noexcept(_Noexcept);
73};
74
75template <class _Tp, class _Mp, class _Gp>
76 requires is_object_v<_Mp>
77struct __function_ref_bind<_Mp _Gp::*, _Tp> {
78 using type _LIBCPP_NODEBUG = invoke_result_t<_Mp _Gp::*, _Tp&>() noexcept;
79};
80
81template <class _Fp, class _Tp>
82using __function_ref_bind_t _LIBCPP_NODEBUG = __function_ref_bind<_Fp, _Tp>::type;
83
84template <class _Fp>
85 requires is_function_v<_Fp>
86function_ref(_Fp*) -> function_ref<_Fp>;
87
88template <auto _Cw, class _Fn>
89 requires is_function_v<remove_pointer_t<_Fn>>
90function_ref(constant_wrapper<_Cw, _Fn>) -> function_ref<remove_pointer_t<_Fn>>;
91
92template <auto _Cw, class _Fn, class _Tp>
93function_ref(constant_wrapper<_Cw, _Fn>, _Tp&&) -> function_ref<__function_ref_bind_t<_Fn, _Tp&>>;
94
95template <class>
96constexpr bool __is_constant_wrapper = false;
97
98template <auto _Value>
99constexpr bool __is_constant_wrapper<constant_wrapper<_Value>> = true;
100
101template <class _Fn, class... _Args>
102concept __statically_callable = requires { _Fn::operator()(std::declval<_Args>()...); };
103
104#endif // _LIBCPP_STD_VER >= 26
105
106_LIBCPP_END_NAMESPACE_STD
107
108#endif // _LIBCPP___FUNCTIONAL_FUNCTION_REF_COMMON_H
109