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