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