Warning: This file is not a C or C++ file. It does not have highlighting.
1 | //===-- include/flang/Common/reference-wrapper.h ----------------*- C++ -*-===// |
---|---|
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 | // clang-format off |
9 | // |
10 | // Implementation of std::reference_wrapper borrowed from libcu++ |
11 | // https://github.com/NVIDIA/libcudacxx/blob/f7e6cd07ed5ba826aeac0b742feafddfedc1e400/include/cuda/std/detail/libcxx/include/__functional/reference_wrapper.h#L1 |
12 | // with modifications. |
13 | // |
14 | // The original source code is distributed under the Apache License v2.0 |
15 | // with LLVM Exceptions. |
16 | // |
17 | // TODO: using libcu++ is the best option for CUDA, but there is a couple |
18 | // of issues: |
19 | // * The include paths need to be set up such that all STD header files |
20 | // are taken from libcu++. |
21 | // * cuda:: namespace need to be forced for all std:: references. |
22 | // |
23 | // clang-format on |
24 | |
25 | #ifndef FORTRAN_COMMON_REFERENCE_WRAPPER_H |
26 | #define FORTRAN_COMMON_REFERENCE_WRAPPER_H |
27 | |
28 | #include "flang/Common/api-attrs.h" |
29 | #include <functional> |
30 | #include <type_traits> |
31 | |
32 | #if !defined(STD_REFERENCE_WRAPPER_UNSUPPORTED) && \ |
33 | (defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__) |
34 | #define STD_REFERENCE_WRAPPER_UNSUPPORTED 1 |
35 | #endif |
36 | |
37 | namespace Fortran::common { |
38 | |
39 | template <class _Tp> |
40 | using __remove_cvref_t = std::remove_cv_t<std::remove_reference_t<_Tp>>; |
41 | template <class _Tp, class _Up> |
42 | struct __is_same_uncvref |
43 | : std::is_same<__remove_cvref_t<_Tp>, __remove_cvref_t<_Up>> {}; |
44 | |
45 | #if STD_REFERENCE_WRAPPER_UNSUPPORTED |
46 | template <class _Tp> class reference_wrapper { |
47 | public: |
48 | // types |
49 | typedef _Tp type; |
50 | |
51 | private: |
52 | type *__f_; |
53 | |
54 | static RT_API_ATTRS void __fun(_Tp &); |
55 | static void __fun(_Tp &&) = delete; |
56 | |
57 | public: |
58 | template <class _Up, |
59 | class = |
60 | std::enable_if_t<!__is_same_uncvref<_Up, reference_wrapper>::value, |
61 | decltype(__fun(std::declval<_Up>()))>> |
62 | constexpr RT_API_ATTRS reference_wrapper(_Up &&__u) { |
63 | type &__f = static_cast<_Up &&>(__u); |
64 | __f_ = std::addressof(__f); |
65 | } |
66 | |
67 | // access |
68 | constexpr RT_API_ATTRS operator type &() const { return *__f_; } |
69 | constexpr RT_API_ATTRS type &get() const { return *__f_; } |
70 | |
71 | // invoke |
72 | template <class... _ArgTypes> |
73 | constexpr RT_API_ATTRS typename std::invoke_result_t<type &, _ArgTypes...> |
74 | operator()(_ArgTypes &&...__args) const { |
75 | return std::invoke(get(), std::forward<_ArgTypes>(__args)...); |
76 | } |
77 | }; |
78 | |
79 | template <class _Tp> reference_wrapper(_Tp &) -> reference_wrapper<_Tp>; |
80 | |
81 | template <class _Tp> |
82 | inline constexpr RT_API_ATTRS reference_wrapper<_Tp> ref(_Tp &__t) { |
83 | return reference_wrapper<_Tp>(__t); |
84 | } |
85 | |
86 | template <class _Tp> |
87 | inline constexpr RT_API_ATTRS reference_wrapper<_Tp> ref( |
88 | reference_wrapper<_Tp> __t) { |
89 | return __t; |
90 | } |
91 | |
92 | template <class _Tp> |
93 | inline constexpr RT_API_ATTRS reference_wrapper<const _Tp> cref( |
94 | const _Tp &__t) { |
95 | return reference_wrapper<const _Tp>(__t); |
96 | } |
97 | |
98 | template <class _Tp> |
99 | inline constexpr RT_API_ATTRS reference_wrapper<const _Tp> cref( |
100 | reference_wrapper<_Tp> __t) { |
101 | return __t; |
102 | } |
103 | |
104 | template <class _Tp> void ref(const _Tp &&) = delete; |
105 | template <class _Tp> void cref(const _Tp &&) = delete; |
106 | #else // !STD_REFERENCE_WRAPPER_UNSUPPORTED |
107 | using std::cref; |
108 | using std::ref; |
109 | using std::reference_wrapper; |
110 | #endif // !STD_REFERENCE_WRAPPER_UNSUPPORTED |
111 | |
112 | } // namespace Fortran::common |
113 | |
114 | #endif // FORTRAN_COMMON_REFERENCE_WRAPPER_H |
115 |
Warning: This file is not a C or C++ file. It does not have highlighting.