]>
Commit | Line | Data |
---|---|---|
e37e6813 VV |
1 | // <experimental/propagate_const> -*- C++ -*- |
2 | ||
7adcbafe | 3 | // Copyright (C) 2015-2022 Free Software Foundation, Inc. |
e37e6813 VV |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
8 | // Free Software Foundation; either version 3, or (at your option) | |
9 | // any later version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
16 | // Under Section 7 of GPL version 3, you are granted additional | |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
24 | ||
25 | /** @file experimental/propagate_const | |
26 | * This is a TS C++ Library header. | |
1ababc8b | 27 | * @ingroup libfund-ts |
e37e6813 VV |
28 | */ |
29 | ||
30 | #ifndef _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST | |
31 | #define _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 1 | |
32 | ||
33 | #pragma GCC system_header | |
34 | ||
d681026d | 35 | #if __cplusplus >= 201402L |
e37e6813 VV |
36 | |
37 | #include <type_traits> | |
d67dd0be JW |
38 | #include <bits/functional_hash.h> |
39 | #include <bits/move.h> | |
40 | #include <bits/stl_function.h> | |
e347987d | 41 | #include <experimental/bits/lfts_config.h> |
e37e6813 VV |
42 | |
43 | namespace std _GLIBCXX_VISIBILITY(default) | |
44 | { | |
4a15d842 FD |
45 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
46 | ||
e37e6813 VV |
47 | namespace experimental |
48 | { | |
49 | inline namespace fundamentals_v2 | |
50 | { | |
e37e6813 VV |
51 | /** |
52 | * @defgroup propagate_const Const-propagating wrapper | |
1ababc8b | 53 | * @ingroup libfund-ts |
e37e6813 VV |
54 | * |
55 | * A const-propagating wrapper that propagates const to pointer-like members, | |
56 | * as described in n4388 "A Proposal to Add a Const-Propagating Wrapper | |
57 | * to the Standard Library". | |
58 | * | |
59 | * @{ | |
60 | */ | |
61 | ||
1ababc8b | 62 | /// Const-propagating wrapper. |
e37e6813 VV |
63 | template <typename _Tp> |
64 | class propagate_const | |
65 | { | |
66 | public: | |
10482a65 | 67 | typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type; |
e37e6813 VV |
68 | |
69 | private: | |
70 | template <typename _Up> | |
71 | struct __is_propagate_const : false_type | |
72 | { }; | |
73 | ||
74 | template <typename _Up> | |
75 | struct __is_propagate_const<propagate_const<_Up>> : true_type | |
76 | { }; | |
77 | ||
78 | template <typename _Up> | |
79 | friend constexpr const _Up& | |
80 | get_underlying(const propagate_const<_Up>& __pt) noexcept; | |
81 | template <typename _Up> | |
82 | friend constexpr _Up& | |
83 | get_underlying(propagate_const<_Up>& __pt) noexcept; | |
84 | ||
85 | template <typename _Up> | |
86 | static constexpr element_type* | |
87 | __to_raw_pointer(_Up* __u) | |
88 | { return __u; } | |
89 | ||
90 | template <typename _Up> | |
91 | static constexpr element_type* | |
92 | __to_raw_pointer(_Up& __u) | |
93 | { return __u.get(); } | |
94 | ||
95 | template <typename _Up> | |
96 | static constexpr const element_type* | |
97 | __to_raw_pointer(const _Up* __u) | |
98 | { return __u; } | |
99 | ||
100 | template <typename _Up> | |
101 | static constexpr const element_type* | |
102 | __to_raw_pointer(const _Up& __u) | |
103 | { return __u.get(); } | |
104 | ||
105 | public: | |
106 | static_assert(__and_<is_object<typename remove_pointer<_Tp>::type>, | |
107 | __not_<is_array<_Tp>>, | |
108 | __or_<is_class<_Tp>, is_pointer<_Tp>>>::value, | |
109 | "propagate_const requires a class or a pointer to an" | |
110 | " object type"); | |
111 | ||
112 | // [propagate_const.ctor], constructors | |
113 | constexpr propagate_const() = default; | |
114 | propagate_const(const propagate_const& __p) = delete; | |
115 | constexpr propagate_const(propagate_const&& __p) = default; | |
d319517e | 116 | |
e37e6813 VV |
117 | template <typename _Up, typename |
118 | enable_if<__and_<is_constructible<_Tp, _Up&&>, | |
119 | is_convertible<_Up&&, _Tp>>::value, bool | |
120 | >::type=true> | |
121 | constexpr propagate_const(propagate_const<_Up>&& __pu) | |
8b649cd3 | 122 | : _M_t(std::move(get_underlying(__pu))) |
e37e6813 | 123 | {} |
d319517e | 124 | |
e37e6813 VV |
125 | template <typename _Up, typename |
126 | enable_if<__and_<is_constructible<_Tp, _Up&&>, | |
127 | __not_<is_convertible<_Up&&, _Tp>>>::value, | |
128 | bool>::type=false> | |
129 | constexpr explicit propagate_const(propagate_const<_Up>&& __pu) | |
8b649cd3 | 130 | : _M_t(std::move(get_underlying(__pu))) |
e37e6813 | 131 | {} |
d319517e | 132 | |
e37e6813 VV |
133 | template <typename _Up, typename |
134 | enable_if<__and_<is_constructible<_Tp, _Up&&>, | |
135 | is_convertible<_Up&&, _Tp>, | |
136 | __not_<__is_propagate_const< | |
137 | typename decay<_Up>::type>> | |
138 | >::value, bool>::type=true> | |
139 | constexpr propagate_const(_Up&& __u) | |
8b649cd3 | 140 | : _M_t(std::forward<_Up>(__u)) |
e37e6813 | 141 | {} |
d319517e | 142 | |
e37e6813 VV |
143 | template <typename _Up, typename |
144 | enable_if<__and_<is_constructible<_Tp, _Up&&>, | |
145 | __not_<is_convertible<_Up&&, _Tp>>, | |
146 | __not_<__is_propagate_const< | |
147 | typename decay<_Up>::type>> | |
148 | >::value, bool>::type=false> | |
149 | constexpr explicit propagate_const(_Up&& __u) | |
8b649cd3 | 150 | : _M_t(std::forward<_Up>(__u)) |
e37e6813 VV |
151 | {} |
152 | ||
153 | // [propagate_const.assignment], assignment | |
154 | propagate_const& operator=(const propagate_const& __p) = delete; | |
155 | constexpr propagate_const& operator=(propagate_const&& __p) = default; | |
156 | ||
157 | template <typename _Up, typename = | |
158 | typename enable_if<is_convertible<_Up&&, _Tp>::value>::type> | |
159 | constexpr propagate_const& operator=(propagate_const<_Up>&& __pu) | |
160 | { | |
8b649cd3 | 161 | _M_t = std::move(get_underlying(__pu)); |
f6cdfe82 | 162 | return *this; |
e37e6813 VV |
163 | } |
164 | ||
165 | template <typename _Up, typename = | |
166 | typename enable_if<__and_<is_convertible<_Up&&, _Tp>, | |
167 | __not_<__is_propagate_const< | |
168 | typename decay<_Up>::type>> | |
169 | >::value>::type> | |
170 | constexpr propagate_const& operator=(_Up&& __u) | |
171 | { | |
8b649cd3 | 172 | _M_t = std::forward<_Up>(__u); |
f6cdfe82 | 173 | return *this; |
e37e6813 VV |
174 | } |
175 | ||
176 | // [propagate_const.const_observers], const observers | |
177 | explicit constexpr operator bool() const | |
178 | { | |
8b649cd3 | 179 | return bool(_M_t); |
e37e6813 VV |
180 | } |
181 | ||
182 | constexpr const element_type* operator->() const | |
183 | { | |
184 | return get(); | |
185 | } | |
186 | ||
187 | template <typename _Up = _Tp, | |
188 | typename enable_if<__or_<is_pointer<_Up>, | |
189 | is_convertible<_Up, | |
190 | const element_type*> | |
191 | >::value, bool>::type = true> | |
192 | constexpr operator const element_type*() const | |
193 | { | |
194 | return get(); | |
195 | } | |
196 | ||
197 | constexpr const element_type& operator*() const | |
198 | { | |
199 | return *get(); | |
200 | } | |
201 | ||
202 | constexpr const element_type* get() const | |
203 | { | |
8b649cd3 | 204 | return __to_raw_pointer(_M_t); |
e37e6813 VV |
205 | } |
206 | ||
207 | // [propagate_const.non_const_observers], non-const observers | |
208 | constexpr element_type* operator->() | |
209 | { | |
210 | return get(); | |
211 | } | |
212 | ||
213 | template <typename _Up = _Tp, | |
214 | typename enable_if<__or_<is_pointer<_Up>, | |
215 | is_convertible<_Up, | |
216 | const element_type*> | |
217 | >::value, bool>::type = true> | |
218 | constexpr operator element_type*() | |
219 | { | |
220 | return get(); | |
221 | } | |
222 | ||
223 | constexpr element_type& operator*() | |
224 | { | |
225 | return *get(); | |
226 | } | |
227 | ||
228 | constexpr element_type* get() | |
229 | { | |
8b649cd3 | 230 | return __to_raw_pointer(_M_t); |
e37e6813 VV |
231 | } |
232 | ||
233 | // [propagate_const.modifiers], modifiers | |
234 | constexpr void | |
235 | swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value) | |
236 | { | |
237 | using std::swap; | |
8b649cd3 | 238 | swap(_M_t, get_underlying(__pt)); |
e37e6813 VV |
239 | } |
240 | ||
241 | private: | |
8b649cd3 | 242 | _Tp _M_t; |
e37e6813 VV |
243 | }; |
244 | ||
245 | // [propagate_const.relational], relational operators | |
246 | template <typename _Tp> | |
247 | constexpr bool | |
248 | operator==(const propagate_const<_Tp>& __pt, nullptr_t) | |
249 | { | |
250 | return get_underlying(__pt) == nullptr; | |
251 | } | |
252 | ||
253 | template <typename _Tp> | |
254 | constexpr bool | |
255 | operator==(nullptr_t, const propagate_const<_Tp>& __pu) | |
256 | { | |
257 | return nullptr == get_underlying(__pu); | |
258 | } | |
259 | ||
260 | template <typename _Tp> | |
261 | constexpr bool | |
262 | operator!=(const propagate_const<_Tp>& __pt, nullptr_t) | |
263 | { | |
264 | return get_underlying(__pt) != nullptr; | |
265 | } | |
266 | ||
267 | template <typename _Tp> | |
268 | constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu) | |
269 | { | |
270 | return nullptr != get_underlying(__pu); | |
271 | } | |
272 | ||
273 | template <typename _Tp, typename _Up> | |
274 | constexpr bool | |
275 | operator==(const propagate_const<_Tp>& __pt, | |
276 | const propagate_const<_Up>& __pu) | |
277 | { | |
278 | return get_underlying(__pt) == get_underlying(__pu); | |
279 | } | |
280 | ||
281 | template <typename _Tp, typename _Up> | |
282 | constexpr bool | |
283 | operator!=(const propagate_const<_Tp>& __pt, | |
284 | const propagate_const<_Up>& __pu) | |
285 | { | |
286 | return get_underlying(__pt) != get_underlying(__pu); | |
287 | } | |
288 | ||
289 | template <typename _Tp, typename _Up> | |
290 | constexpr bool | |
291 | operator<(const propagate_const<_Tp>& __pt, | |
292 | const propagate_const<_Up>& __pu) | |
293 | { | |
294 | return get_underlying(__pt) < get_underlying(__pu); | |
295 | } | |
296 | ||
297 | template <typename _Tp, typename _Up> | |
298 | constexpr bool | |
299 | operator>(const propagate_const<_Tp>& __pt, | |
300 | const propagate_const<_Up>& __pu) | |
301 | { | |
302 | return get_underlying(__pt) > get_underlying(__pu); | |
303 | } | |
304 | ||
305 | template <typename _Tp, typename _Up> | |
306 | constexpr bool | |
307 | operator<=(const propagate_const<_Tp>& __pt, | |
308 | const propagate_const<_Up>& __pu) | |
309 | { | |
310 | return get_underlying(__pt) <= get_underlying(__pu); | |
311 | } | |
312 | ||
313 | template <typename _Tp, typename _Up> | |
314 | constexpr bool | |
315 | operator>=(const propagate_const<_Tp>& __pt, | |
316 | const propagate_const<_Up>& __pu) | |
317 | { | |
318 | return get_underlying(__pt) >= get_underlying(__pu); | |
319 | } | |
320 | ||
321 | template <typename _Tp, typename _Up> | |
322 | constexpr bool | |
323 | operator==(const propagate_const<_Tp>& __pt, const _Up& __u) | |
324 | { | |
325 | return get_underlying(__pt) == __u; | |
326 | } | |
327 | ||
328 | template <typename _Tp, typename _Up> | |
329 | constexpr bool | |
330 | operator!=(const propagate_const<_Tp>& __pt, const _Up& __u) | |
331 | { | |
332 | return get_underlying(__pt) != __u; | |
333 | } | |
334 | ||
335 | template <typename _Tp, typename _Up> | |
336 | constexpr bool | |
337 | operator<(const propagate_const<_Tp>& __pt, const _Up& __u) | |
338 | { | |
339 | return get_underlying(__pt) < __u; | |
340 | } | |
341 | ||
342 | template <typename _Tp, typename _Up> | |
343 | constexpr bool | |
344 | operator>(const propagate_const<_Tp>& __pt, const _Up& __u) | |
345 | { | |
346 | return get_underlying(__pt) > __u; | |
347 | } | |
348 | ||
349 | template <typename _Tp, typename _Up> | |
350 | constexpr bool | |
351 | operator<=(const propagate_const<_Tp>& __pt, const _Up& __u) | |
352 | { | |
353 | return get_underlying(__pt) <= __u; | |
354 | } | |
355 | ||
356 | template <typename _Tp, typename _Up> | |
357 | constexpr bool | |
358 | operator>=(const propagate_const<_Tp>& __pt, const _Up& __u) | |
359 | { | |
360 | return get_underlying(__pt) >= __u; | |
361 | } | |
362 | ||
363 | template <typename _Tp, typename _Up> | |
364 | constexpr bool | |
365 | operator==(const _Tp& __t, const propagate_const<_Up>& __pu) | |
366 | { | |
367 | return __t == get_underlying(__pu); | |
368 | } | |
369 | ||
370 | template <typename _Tp, typename _Up> | |
371 | constexpr bool | |
372 | operator!=(const _Tp& __t, const propagate_const<_Up>& __pu) | |
373 | { | |
374 | return __t != get_underlying(__pu); | |
375 | } | |
376 | ||
377 | template <typename _Tp, typename _Up> | |
378 | constexpr bool | |
379 | operator<(const _Tp& __t, const propagate_const<_Up>& __pu) | |
380 | { | |
381 | return __t < get_underlying(__pu); | |
382 | } | |
383 | ||
384 | template <typename _Tp, typename _Up> | |
385 | constexpr bool | |
386 | operator>(const _Tp& __t, const propagate_const<_Up>& __pu) | |
387 | { | |
388 | return __t > get_underlying(__pu); | |
389 | } | |
390 | ||
391 | template <typename _Tp, typename _Up> | |
392 | constexpr bool | |
393 | operator<=(const _Tp& __t, const propagate_const<_Up>& __pu) | |
394 | { | |
395 | return __t <= get_underlying(__pu); | |
396 | } | |
397 | ||
398 | template <typename _Tp, typename _Up> | |
399 | constexpr bool | |
400 | operator>=(const _Tp& __t, const propagate_const<_Up>& __pu) | |
401 | { | |
402 | return __t >= get_underlying(__pu); | |
403 | } | |
404 | ||
405 | // [propagate_const.algorithms], specialized algorithms | |
d319517e JW |
406 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
407 | // 3413. propagate_const's swap [...] needs to be constrained and use a trait | |
e37e6813 | 408 | template <typename _Tp> |
d319517e | 409 | constexpr enable_if_t<__is_swappable<_Tp>::value, void> |
e37e6813 VV |
410 | swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2) |
411 | noexcept(__is_nothrow_swappable<_Tp>::value) | |
412 | { | |
413 | __pt.swap(__pt2); | |
414 | } | |
415 | ||
416 | // [propagate_const.underlying], underlying pointer access | |
417 | template <typename _Tp> | |
418 | constexpr const _Tp& | |
419 | get_underlying(const propagate_const<_Tp>& __pt) noexcept | |
420 | { | |
8b649cd3 | 421 | return __pt._M_t; |
e37e6813 VV |
422 | } |
423 | ||
424 | template <typename _Tp> | |
425 | constexpr _Tp& | |
426 | get_underlying(propagate_const<_Tp>& __pt) noexcept | |
427 | { | |
8b649cd3 | 428 | return __pt._M_t; |
e37e6813 VV |
429 | } |
430 | ||
f0b88346 | 431 | /// @} group propagate_const |
e37e6813 VV |
432 | } // namespace fundamentals_v2 |
433 | } // namespace experimental | |
434 | ||
435 | // [propagate_const.hash], hash support | |
436 | template <typename _Tp> | |
437 | struct hash<experimental::propagate_const<_Tp>> | |
438 | { | |
439 | using result_type = size_t; | |
440 | using argument_type = experimental::propagate_const<_Tp>; | |
441 | ||
442 | size_t | |
443 | operator()(const experimental::propagate_const<_Tp>& __t) const | |
444 | noexcept(noexcept(hash<_Tp>{}(get_underlying(__t)))) | |
445 | { | |
446 | return hash<_Tp>{}(get_underlying(__t)); | |
447 | } | |
448 | }; | |
449 | ||
450 | // [propagate_const.comparison_function_objects], comparison function objects | |
451 | template <typename _Tp> | |
452 | struct equal_to<experimental::propagate_const<_Tp>> | |
453 | { | |
454 | constexpr bool | |
455 | operator()(const experimental::propagate_const<_Tp>& __x, | |
456 | const experimental::propagate_const<_Tp>& __y) const | |
457 | { | |
458 | return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y)); | |
459 | } | |
460 | ||
461 | typedef experimental::propagate_const<_Tp> first_argument_type; | |
462 | typedef experimental::propagate_const<_Tp> second_argument_type; | |
463 | typedef bool result_type; | |
464 | }; | |
465 | ||
466 | template <typename _Tp> | |
467 | struct not_equal_to<experimental::propagate_const<_Tp>> | |
468 | { | |
469 | constexpr bool | |
470 | operator()(const experimental::propagate_const<_Tp>& __x, | |
471 | const experimental::propagate_const<_Tp>& __y) const | |
472 | { | |
473 | return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y)); | |
474 | } | |
475 | ||
476 | typedef experimental::propagate_const<_Tp> first_argument_type; | |
477 | typedef experimental::propagate_const<_Tp> second_argument_type; | |
478 | typedef bool result_type; | |
479 | }; | |
480 | ||
481 | template <typename _Tp> | |
482 | struct less<experimental::propagate_const<_Tp>> | |
483 | { | |
484 | constexpr bool | |
485 | operator()(const experimental::propagate_const<_Tp>& __x, | |
486 | const experimental::propagate_const<_Tp>& __y) const | |
487 | { | |
488 | return less<_Tp>{}(get_underlying(__x), get_underlying(__y)); | |
489 | } | |
490 | ||
491 | typedef experimental::propagate_const<_Tp> first_argument_type; | |
492 | typedef experimental::propagate_const<_Tp> second_argument_type; | |
493 | typedef bool result_type; | |
494 | }; | |
495 | ||
496 | template <typename _Tp> | |
497 | struct greater<experimental::propagate_const<_Tp>> | |
498 | { | |
499 | constexpr bool | |
500 | operator()(const experimental::propagate_const<_Tp>& __x, | |
501 | const experimental::propagate_const<_Tp>& __y) const | |
502 | { | |
503 | return greater<_Tp>{}(get_underlying(__x), get_underlying(__y)); | |
504 | } | |
505 | ||
506 | typedef experimental::propagate_const<_Tp> first_argument_type; | |
507 | typedef experimental::propagate_const<_Tp> second_argument_type; | |
508 | typedef bool result_type; | |
509 | }; | |
510 | ||
511 | template <typename _Tp> | |
512 | struct less_equal<experimental::propagate_const<_Tp>> | |
513 | { | |
514 | constexpr bool | |
515 | operator()(const experimental::propagate_const<_Tp>& __x, | |
516 | const experimental::propagate_const<_Tp>& __y) const | |
517 | { | |
518 | return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y)); | |
519 | } | |
520 | ||
521 | typedef experimental::propagate_const<_Tp> first_argument_type; | |
522 | typedef experimental::propagate_const<_Tp> second_argument_type; | |
523 | typedef bool result_type; | |
524 | }; | |
525 | ||
526 | template <typename _Tp> | |
527 | struct greater_equal<experimental::propagate_const<_Tp>> | |
528 | { | |
529 | constexpr bool | |
530 | operator()(const experimental::propagate_const<_Tp>& __x, | |
531 | const experimental::propagate_const<_Tp>& __y) const | |
532 | { | |
533 | return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y)); | |
534 | } | |
535 | ||
536 | typedef experimental::propagate_const<_Tp> first_argument_type; | |
537 | typedef experimental::propagate_const<_Tp> second_argument_type; | |
538 | typedef bool result_type; | |
539 | }; | |
4a15d842 FD |
540 | |
541 | _GLIBCXX_END_NAMESPACE_VERSION | |
e37e6813 VV |
542 | } // namespace std |
543 | ||
544 | #endif // C++14 | |
545 | ||
546 | #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST |