libstdc++
propagate_const
Go to the documentation of this file.
1// <experimental/propagate_const> -*- C++ -*-
2
3// Copyright (C) 2015-2021 Free Software Foundation, Inc.
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.
27 * @ingroup libfund-ts
28 */
29
30#ifndef _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST
31#define _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 1
32
33#pragma GCC system_header
34
35#if __cplusplus >= 201402L
36
37#include <type_traits>
39#include <bits/move.h>
40#include <bits/stl_function.h>
42
43namespace std _GLIBCXX_VISIBILITY(default)
44{
45_GLIBCXX_BEGIN_NAMESPACE_VERSION
46
47namespace experimental
48{
49inline namespace fundamentals_v2
50{
51 /**
52 * @defgroup propagate_const Const-propagating wrapper
53 * @ingroup libfund-ts
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
62 /// Const-propagating wrapper.
63 template <typename _Tp>
64 class propagate_const
65 {
66 public:
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;
116
117 template <typename _Up, typename
119 is_convertible<_Up&&, _Tp>>::value, bool
120 >::type=true>
121 constexpr propagate_const(propagate_const<_Up>&& __pu)
122 : _M_t(std::move(get_underlying(__pu)))
123 {}
124
125 template <typename _Up, typename
127 __not_<is_convertible<_Up&&, _Tp>>>::value,
128 bool>::type=false>
129 constexpr explicit propagate_const(propagate_const<_Up>&& __pu)
130 : _M_t(std::move(get_underlying(__pu)))
131 {}
132
133 template <typename _Up, typename
136 __not_<__is_propagate_const<
137 typename decay<_Up>::type>>
138 >::value, bool>::type=true>
139 constexpr propagate_const(_Up&& __u)
140 : _M_t(std::forward<_Up>(__u))
141 {}
142
143 template <typename _Up, typename
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)
150 : _M_t(std::forward<_Up>(__u))
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 =
159 constexpr propagate_const& operator=(propagate_const<_Up>&& __pu)
160 {
161 _M_t = std::move(get_underlying(__pu));
162 return *this;
163 }
164
165 template <typename _Up, typename =
167 __not_<__is_propagate_const<
168 typename decay<_Up>::type>>
169 >::value>::type>
170 constexpr propagate_const& operator=(_Up&& __u)
171 {
172 _M_t = std::forward<_Up>(__u);
173 return *this;
174 }
175
176 // [propagate_const.const_observers], const observers
177 explicit constexpr operator bool() const
178 {
179 return bool(_M_t);
180 }
181
182 constexpr const element_type* operator->() const
183 {
184 return get();
185 }
186
187 template <typename _Up = _Tp,
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 {
204 return __to_raw_pointer(_M_t);
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,
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 {
230 return __to_raw_pointer(_M_t);
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;
238 swap(_M_t, get_underlying(__pt));
239 }
240
241 private:
242 _Tp _M_t;
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
406 // _GLIBCXX_RESOLVE_LIB_DEFECTS
407 // 3413. propagate_const's swap [...] needs to be constrained and use a trait
408 template <typename _Tp>
409 constexpr enable_if_t<__is_swappable<_Tp>::value, void>
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 {
421 return __pt._M_t;
422 }
423
424 template <typename _Tp>
425 constexpr _Tp&
426 get_underlying(propagate_const<_Tp>& __pt) noexcept
427 {
428 return __pt._M_t;
429 }
430
431 /// @} group propagate_const
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 };
540
541_GLIBCXX_END_NAMESPACE_VERSION
542} // namespace std
543
544#endif // C++14
545
546#endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST
typename remove_reference< _Tp >::type remove_reference_t
Alias template for remove_reference.
Definition type_traits:1637
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Definition type_traits:83
integral_constant< bool, false > false_type
The type used as a compile-time boolean with false value.
Definition type_traits:86
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:104
void swap(any &__x, any &__y) noexcept
Exchange the states of two any objects.
Definition any:428
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:77
ISO C++ entities toplevel namespace is std.
Namespace for features defined in ISO Technical Specifications.
Primary class template hash.
is_pointer
Definition type_traits:451
is_convertible
Definition type_traits:1458
Define a member typedef type only if a boolean constant is true.
Definition type_traits:2192
One of the comparison functors.
One of the comparison functors.
One of the comparison functors.
One of the comparison functors.
One of the comparison functors.
One of the comparison functors.