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