1 // <experimental/propagate_const> -*- C++ -*-
3 // Copyright (C) 2015 Free Software Foundation, Inc.
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)
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.
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.
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/>.
25 /** @file experimental/propagate_const
26 * This is a TS C++ Library header.
29 #ifndef _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST
30 #define _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 1
32 #pragma GCC system_header
34 #if __cplusplus <= 201103L
35 # include <bits/c++14_warning.h>
38 #include <type_traits>
41 namespace std _GLIBCXX_VISIBILITY(default)
43 namespace experimental
45 inline namespace fundamentals_v2
47 _GLIBCXX_BEGIN_NAMESPACE_VERSION
50 * @defgroup propagate_const Const-propagating wrapper
51 * @ingroup experimental
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".
60 /// Const-propagating wrapper.
61 template <typename _Tp>
65 typedef remove_reference_t<decltype(*declval<_Tp&>())> element_type;
68 template <typename _Up>
69 struct __is_propagate_const : false_type
72 template <typename _Up>
73 struct __is_propagate_const<propagate_const<_Up>> : true_type
76 template <typename _Up>
77 friend constexpr const _Up&
78 get_underlying(const propagate_const<_Up>& __pt) noexcept;
79 template <typename _Up>
81 get_underlying(propagate_const<_Up>& __pt) noexcept;
83 template <typename _Up>
84 static constexpr element_type*
85 __to_raw_pointer(_Up* __u)
88 template <typename _Up>
89 static constexpr element_type*
90 __to_raw_pointer(_Up& __u)
93 template <typename _Up>
94 static constexpr const element_type*
95 __to_raw_pointer(const _Up* __u)
98 template <typename _Up>
99 static constexpr const element_type*
100 __to_raw_pointer(const _Up& __u)
101 { return __u.get(); }
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"
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
118 constexpr propagate_const(propagate_const<_Up>&& __pu)
119 : __t(move(get_underlying(__pu)))
121 template <typename _Up, typename
122 enable_if<__and_<is_constructible<_Tp, _Up&&>,
123 __not_<is_convertible<_Up&&, _Tp>>>::value,
125 constexpr explicit propagate_const(propagate_const<_Up>&& __pu)
126 : __t(move(get_underlying(__pu)))
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))
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))
147 // [propagate_const.assignment], assignment
148 propagate_const& operator=(const propagate_const& __p) = delete;
149 constexpr propagate_const& operator=(propagate_const&& __p) = default;
151 template <typename _Up, typename =
152 typename enable_if<is_convertible<_Up&&, _Tp>::value>::type>
153 constexpr propagate_const& operator=(propagate_const<_Up>&& __pu)
155 __t = move(get_underlying(__pu));
158 template <typename _Up, typename =
159 typename enable_if<__and_<is_convertible<_Up&&, _Tp>,
160 __not_<__is_propagate_const<
161 typename decay<_Up>::type>>
163 constexpr propagate_const& operator=(_Up&& __u)
165 __t = forward<_Up>(__u);
168 // [propagate_const.const_observers], const observers
169 explicit constexpr operator bool() const
174 constexpr const element_type* operator->() const
179 template <typename _Up = _Tp,
180 typename enable_if<__or_<is_pointer<_Up>,
183 >::value, bool>::type = true>
184 constexpr operator const element_type*() const
189 constexpr const element_type& operator*() const
194 constexpr const element_type* get() const
196 return __to_raw_pointer(__t);
199 // [propagate_const.non_const_observers], non-const observers
200 constexpr element_type* operator->()
205 template <typename _Up = _Tp,
206 typename enable_if<__or_<is_pointer<_Up>,
209 >::value, bool>::type = true>
210 constexpr operator element_type*()
215 constexpr element_type& operator*()
220 constexpr element_type* get()
222 return __to_raw_pointer(__t);
225 // [propagate_const.modifiers], modifiers
227 swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value)
230 swap(__t, get_underlying(__pt));
234 _Tp __t; //exposition only
237 // [propagate_const.relational], relational operators
238 template <typename _Tp>
240 operator==(const propagate_const<_Tp>& __pt, nullptr_t)
242 return get_underlying(__pt) == nullptr;
245 template <typename _Tp>
247 operator==(nullptr_t, const propagate_const<_Tp>& __pu)
249 return nullptr == get_underlying(__pu);
252 template <typename _Tp>
254 operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
256 return get_underlying(__pt) != nullptr;
259 template <typename _Tp>
260 constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu)
262 return nullptr != get_underlying(__pu);
265 template <typename _Tp, typename _Up>
267 operator==(const propagate_const<_Tp>& __pt,
268 const propagate_const<_Up>& __pu)
270 return get_underlying(__pt) == get_underlying(__pu);
273 template <typename _Tp, typename _Up>
275 operator!=(const propagate_const<_Tp>& __pt,
276 const propagate_const<_Up>& __pu)
278 return get_underlying(__pt) != get_underlying(__pu);
281 template <typename _Tp, typename _Up>
283 operator<(const propagate_const<_Tp>& __pt,
284 const propagate_const<_Up>& __pu)
286 return get_underlying(__pt) < get_underlying(__pu);
289 template <typename _Tp, typename _Up>
291 operator>(const propagate_const<_Tp>& __pt,
292 const propagate_const<_Up>& __pu)
294 return get_underlying(__pt) > get_underlying(__pu);
297 template <typename _Tp, typename _Up>
299 operator<=(const propagate_const<_Tp>& __pt,
300 const propagate_const<_Up>& __pu)
302 return get_underlying(__pt) <= get_underlying(__pu);
305 template <typename _Tp, typename _Up>
307 operator>=(const propagate_const<_Tp>& __pt,
308 const propagate_const<_Up>& __pu)
310 return get_underlying(__pt) >= get_underlying(__pu);
313 template <typename _Tp, typename _Up>
315 operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
317 return get_underlying(__pt) == __u;
320 template <typename _Tp, typename _Up>
322 operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
324 return get_underlying(__pt) != __u;
327 template <typename _Tp, typename _Up>
329 operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
331 return get_underlying(__pt) < __u;
334 template <typename _Tp, typename _Up>
336 operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
338 return get_underlying(__pt) > __u;
341 template <typename _Tp, typename _Up>
343 operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
345 return get_underlying(__pt) <= __u;
348 template <typename _Tp, typename _Up>
350 operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
352 return get_underlying(__pt) >= __u;
355 template <typename _Tp, typename _Up>
357 operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
359 return __t == get_underlying(__pu);
362 template <typename _Tp, typename _Up>
364 operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
366 return __t != get_underlying(__pu);
369 template <typename _Tp, typename _Up>
371 operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
373 return __t < get_underlying(__pu);
376 template <typename _Tp, typename _Up>
378 operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
380 return __t > get_underlying(__pu);
383 template <typename _Tp, typename _Up>
385 operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
387 return __t <= get_underlying(__pu);
390 template <typename _Tp, typename _Up>
392 operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
394 return __t >= get_underlying(__pu);
397 // [propagate_const.algorithms], specialized algorithms
398 template <typename _Tp>
400 swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2)
401 noexcept(__is_nothrow_swappable<_Tp>::value)
406 // [propagate_const.underlying], underlying pointer access
407 template <typename _Tp>
409 get_underlying(const propagate_const<_Tp>& __pt) noexcept
414 template <typename _Tp>
416 get_underlying(propagate_const<_Tp>& __pt) noexcept
421 // @} group propagate_const
422 _GLIBCXX_END_NAMESPACE_VERSION
423 } // namespace fundamentals_v2
424 } // namespace experimental
426 // [propagate_const.hash], hash support
427 template <typename _Tp>
428 struct hash<experimental::propagate_const<_Tp>>
430 using result_type = size_t;
431 using argument_type = experimental::propagate_const<_Tp>;
434 operator()(const experimental::propagate_const<_Tp>& __t) const
435 noexcept(noexcept(hash<_Tp>{}(get_underlying(__t))))
437 return hash<_Tp>{}(get_underlying(__t));
441 // [propagate_const.comparison_function_objects], comparison function objects
442 template <typename _Tp>
443 struct equal_to<experimental::propagate_const<_Tp>>
446 operator()(const experimental::propagate_const<_Tp>& __x,
447 const experimental::propagate_const<_Tp>& __y) const
449 return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
452 typedef experimental::propagate_const<_Tp> first_argument_type;
453 typedef experimental::propagate_const<_Tp> second_argument_type;
454 typedef bool result_type;
457 template <typename _Tp>
458 struct not_equal_to<experimental::propagate_const<_Tp>>
461 operator()(const experimental::propagate_const<_Tp>& __x,
462 const experimental::propagate_const<_Tp>& __y) const
464 return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
467 typedef experimental::propagate_const<_Tp> first_argument_type;
468 typedef experimental::propagate_const<_Tp> second_argument_type;
469 typedef bool result_type;
472 template <typename _Tp>
473 struct less<experimental::propagate_const<_Tp>>
476 operator()(const experimental::propagate_const<_Tp>& __x,
477 const experimental::propagate_const<_Tp>& __y) const
479 return less<_Tp>{}(get_underlying(__x), get_underlying(__y));
482 typedef experimental::propagate_const<_Tp> first_argument_type;
483 typedef experimental::propagate_const<_Tp> second_argument_type;
484 typedef bool result_type;
487 template <typename _Tp>
488 struct greater<experimental::propagate_const<_Tp>>
491 operator()(const experimental::propagate_const<_Tp>& __x,
492 const experimental::propagate_const<_Tp>& __y) const
494 return greater<_Tp>{}(get_underlying(__x), get_underlying(__y));
497 typedef experimental::propagate_const<_Tp> first_argument_type;
498 typedef experimental::propagate_const<_Tp> second_argument_type;
499 typedef bool result_type;
502 template <typename _Tp>
503 struct less_equal<experimental::propagate_const<_Tp>>
506 operator()(const experimental::propagate_const<_Tp>& __x,
507 const experimental::propagate_const<_Tp>& __y) const
509 return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
512 typedef experimental::propagate_const<_Tp> first_argument_type;
513 typedef experimental::propagate_const<_Tp> second_argument_type;
514 typedef bool result_type;
517 template <typename _Tp>
518 struct greater_equal<experimental::propagate_const<_Tp>>
521 operator()(const experimental::propagate_const<_Tp>& __x,
522 const experimental::propagate_const<_Tp>& __y) const
524 return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
527 typedef experimental::propagate_const<_Tp> first_argument_type;
528 typedef experimental::propagate_const<_Tp> second_argument_type;
529 typedef bool result_type;
535 #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST