1 // <experimental/propagate_const> -*- C++ -*-
3 // Copyright (C) 2015-2016 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>
40 #include <experimental/bits/lfts_config.h>
42 namespace std _GLIBCXX_VISIBILITY(default)
44 namespace experimental
46 inline namespace fundamentals_v2
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
51 * @defgroup propagate_const Const-propagating wrapper
52 * @ingroup experimental
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".
61 /// Const-propagating wrapper.
62 template <typename _Tp>
66 typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type;
69 template <typename _Up>
70 struct __is_propagate_const : false_type
73 template <typename _Up>
74 struct __is_propagate_const<propagate_const<_Up>> : true_type
77 template <typename _Up>
78 friend constexpr const _Up&
79 get_underlying(const propagate_const<_Up>& __pt) noexcept;
80 template <typename _Up>
82 get_underlying(propagate_const<_Up>& __pt) noexcept;
84 template <typename _Up>
85 static constexpr element_type*
86 __to_raw_pointer(_Up* __u)
89 template <typename _Up>
90 static constexpr element_type*
91 __to_raw_pointer(_Up& __u)
94 template <typename _Up>
95 static constexpr const element_type*
96 __to_raw_pointer(const _Up* __u)
99 template <typename _Up>
100 static constexpr const element_type*
101 __to_raw_pointer(const _Up& __u)
102 { return __u.get(); }
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"
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
119 constexpr propagate_const(propagate_const<_Up>&& __pu)
120 : _M_t(std::move(get_underlying(__pu)))
122 template <typename _Up, typename
123 enable_if<__and_<is_constructible<_Tp, _Up&&>,
124 __not_<is_convertible<_Up&&, _Tp>>>::value,
126 constexpr explicit propagate_const(propagate_const<_Up>&& __pu)
127 : _M_t(std::move(get_underlying(__pu)))
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))
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))
148 // [propagate_const.assignment], assignment
149 propagate_const& operator=(const propagate_const& __p) = delete;
150 constexpr propagate_const& operator=(propagate_const&& __p) = default;
152 template <typename _Up, typename =
153 typename enable_if<is_convertible<_Up&&, _Tp>::value>::type>
154 constexpr propagate_const& operator=(propagate_const<_Up>&& __pu)
156 _M_t = std::move(get_underlying(__pu));
159 template <typename _Up, typename =
160 typename enable_if<__and_<is_convertible<_Up&&, _Tp>,
161 __not_<__is_propagate_const<
162 typename decay<_Up>::type>>
164 constexpr propagate_const& operator=(_Up&& __u)
166 _M_t = std::forward<_Up>(__u);
169 // [propagate_const.const_observers], const observers
170 explicit constexpr operator bool() const
175 constexpr const element_type* operator->() const
180 template <typename _Up = _Tp,
181 typename enable_if<__or_<is_pointer<_Up>,
184 >::value, bool>::type = true>
185 constexpr operator const element_type*() const
190 constexpr const element_type& operator*() const
195 constexpr const element_type* get() const
197 return __to_raw_pointer(_M_t);
200 // [propagate_const.non_const_observers], non-const observers
201 constexpr element_type* operator->()
206 template <typename _Up = _Tp,
207 typename enable_if<__or_<is_pointer<_Up>,
210 >::value, bool>::type = true>
211 constexpr operator element_type*()
216 constexpr element_type& operator*()
221 constexpr element_type* get()
223 return __to_raw_pointer(_M_t);
226 // [propagate_const.modifiers], modifiers
228 swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value)
231 swap(_M_t, get_underlying(__pt));
238 // [propagate_const.relational], relational operators
239 template <typename _Tp>
241 operator==(const propagate_const<_Tp>& __pt, nullptr_t)
243 return get_underlying(__pt) == nullptr;
246 template <typename _Tp>
248 operator==(nullptr_t, const propagate_const<_Tp>& __pu)
250 return nullptr == get_underlying(__pu);
253 template <typename _Tp>
255 operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
257 return get_underlying(__pt) != nullptr;
260 template <typename _Tp>
261 constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu)
263 return nullptr != get_underlying(__pu);
266 template <typename _Tp, typename _Up>
268 operator==(const propagate_const<_Tp>& __pt,
269 const propagate_const<_Up>& __pu)
271 return get_underlying(__pt) == get_underlying(__pu);
274 template <typename _Tp, typename _Up>
276 operator!=(const propagate_const<_Tp>& __pt,
277 const propagate_const<_Up>& __pu)
279 return get_underlying(__pt) != get_underlying(__pu);
282 template <typename _Tp, typename _Up>
284 operator<(const propagate_const<_Tp>& __pt,
285 const propagate_const<_Up>& __pu)
287 return get_underlying(__pt) < get_underlying(__pu);
290 template <typename _Tp, typename _Up>
292 operator>(const propagate_const<_Tp>& __pt,
293 const propagate_const<_Up>& __pu)
295 return get_underlying(__pt) > get_underlying(__pu);
298 template <typename _Tp, typename _Up>
300 operator<=(const propagate_const<_Tp>& __pt,
301 const propagate_const<_Up>& __pu)
303 return get_underlying(__pt) <= get_underlying(__pu);
306 template <typename _Tp, typename _Up>
308 operator>=(const propagate_const<_Tp>& __pt,
309 const propagate_const<_Up>& __pu)
311 return get_underlying(__pt) >= get_underlying(__pu);
314 template <typename _Tp, typename _Up>
316 operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
318 return get_underlying(__pt) == __u;
321 template <typename _Tp, typename _Up>
323 operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
325 return get_underlying(__pt) != __u;
328 template <typename _Tp, typename _Up>
330 operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
332 return get_underlying(__pt) < __u;
335 template <typename _Tp, typename _Up>
337 operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
339 return get_underlying(__pt) > __u;
342 template <typename _Tp, typename _Up>
344 operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
346 return get_underlying(__pt) <= __u;
349 template <typename _Tp, typename _Up>
351 operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
353 return get_underlying(__pt) >= __u;
356 template <typename _Tp, typename _Up>
358 operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
360 return __t == get_underlying(__pu);
363 template <typename _Tp, typename _Up>
365 operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
367 return __t != get_underlying(__pu);
370 template <typename _Tp, typename _Up>
372 operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
374 return __t < get_underlying(__pu);
377 template <typename _Tp, typename _Up>
379 operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
381 return __t > get_underlying(__pu);
384 template <typename _Tp, typename _Up>
386 operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
388 return __t <= get_underlying(__pu);
391 template <typename _Tp, typename _Up>
393 operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
395 return __t >= get_underlying(__pu);
398 // [propagate_const.algorithms], specialized algorithms
399 template <typename _Tp>
401 swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2)
402 noexcept(__is_nothrow_swappable<_Tp>::value)
407 // [propagate_const.underlying], underlying pointer access
408 template <typename _Tp>
410 get_underlying(const propagate_const<_Tp>& __pt) noexcept
415 template <typename _Tp>
417 get_underlying(propagate_const<_Tp>& __pt) noexcept
422 // @} group propagate_const
423 _GLIBCXX_END_NAMESPACE_VERSION
424 } // namespace fundamentals_v2
425 } // namespace experimental
427 // [propagate_const.hash], hash support
428 template <typename _Tp>
429 struct hash<experimental::propagate_const<_Tp>>
431 using result_type = size_t;
432 using argument_type = experimental::propagate_const<_Tp>;
435 operator()(const experimental::propagate_const<_Tp>& __t) const
436 noexcept(noexcept(hash<_Tp>{}(get_underlying(__t))))
438 return hash<_Tp>{}(get_underlying(__t));
442 // [propagate_const.comparison_function_objects], comparison function objects
443 template <typename _Tp>
444 struct equal_to<experimental::propagate_const<_Tp>>
447 operator()(const experimental::propagate_const<_Tp>& __x,
448 const experimental::propagate_const<_Tp>& __y) const
450 return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
453 typedef experimental::propagate_const<_Tp> first_argument_type;
454 typedef experimental::propagate_const<_Tp> second_argument_type;
455 typedef bool result_type;
458 template <typename _Tp>
459 struct not_equal_to<experimental::propagate_const<_Tp>>
462 operator()(const experimental::propagate_const<_Tp>& __x,
463 const experimental::propagate_const<_Tp>& __y) const
465 return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
468 typedef experimental::propagate_const<_Tp> first_argument_type;
469 typedef experimental::propagate_const<_Tp> second_argument_type;
470 typedef bool result_type;
473 template <typename _Tp>
474 struct less<experimental::propagate_const<_Tp>>
477 operator()(const experimental::propagate_const<_Tp>& __x,
478 const experimental::propagate_const<_Tp>& __y) const
480 return less<_Tp>{}(get_underlying(__x), get_underlying(__y));
483 typedef experimental::propagate_const<_Tp> first_argument_type;
484 typedef experimental::propagate_const<_Tp> second_argument_type;
485 typedef bool result_type;
488 template <typename _Tp>
489 struct greater<experimental::propagate_const<_Tp>>
492 operator()(const experimental::propagate_const<_Tp>& __x,
493 const experimental::propagate_const<_Tp>& __y) const
495 return greater<_Tp>{}(get_underlying(__x), get_underlying(__y));
498 typedef experimental::propagate_const<_Tp> first_argument_type;
499 typedef experimental::propagate_const<_Tp> second_argument_type;
500 typedef bool result_type;
503 template <typename _Tp>
504 struct less_equal<experimental::propagate_const<_Tp>>
507 operator()(const experimental::propagate_const<_Tp>& __x,
508 const experimental::propagate_const<_Tp>& __y) const
510 return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
513 typedef experimental::propagate_const<_Tp> first_argument_type;
514 typedef experimental::propagate_const<_Tp> second_argument_type;
515 typedef bool result_type;
518 template <typename _Tp>
519 struct greater_equal<experimental::propagate_const<_Tp>>
522 operator()(const experimental::propagate_const<_Tp>& __x,
523 const experimental::propagate_const<_Tp>& __y) const
525 return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
528 typedef experimental::propagate_const<_Tp> first_argument_type;
529 typedef experimental::propagate_const<_Tp> second_argument_type;
530 typedef bool result_type;
536 #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST