S/390: Add static OSC breaker if necessary.
[official-gcc.git] / libstdc++-v3 / include / experimental / propagate_const
blob5f32111fbba241105f7a581cb6bf0f41a3e94867
1 // <experimental/propagate_const> -*- C++ -*-
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.
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.
27  */
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>
36 #else
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>
44 namespace std _GLIBCXX_VISIBILITY(default)
46 namespace experimental
48 inline namespace fundamentals_v2
50 _GLIBCXX_BEGIN_NAMESPACE_VERSION
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    */
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;
70     private:
71       template <typename _Up>
72         struct __is_propagate_const : false_type
73         { };
75       template <typename _Up>
76         struct __is_propagate_const<propagate_const<_Up>> : true_type
77         { };
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;
86       template <typename _Up>
87         static constexpr element_type*
88         __to_raw_pointer(_Up* __u)
89         { return __u; }
91       template <typename _Up>
92         static constexpr element_type*
93         __to_raw_pointer(_Up& __u)
94         { return __u.get(); }
96       template <typename _Up>
97         static constexpr const element_type*
98         __to_raw_pointer(const _Up* __u)
99         { return __u; }
101       template <typename _Up>
102         static constexpr const element_type*
103         __to_raw_pointer(const _Up& __u)
104         { return __u.get(); }
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");
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       {}
150       // [propagate_const.assignment], assignment
151       propagate_const& operator=(const propagate_const& __p) = delete;
152       constexpr propagate_const& operator=(propagate_const&& __p) = default;
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       }
161       template <typename _Up, typename =
162                 typename enable_if<__and_<is_convertible<_Up&&, _Tp>,
163                                           __not_<__is_propagate_const<
164                                                    typename decay<_Up>::type>>
165                                           >::value>::type>
166       constexpr propagate_const& operator=(_Up&& __u)
167       {
168         _M_t = std::forward<_Up>(__u);
169       }
171       // [propagate_const.const_observers], const observers
172       explicit constexpr operator bool() const
173       {
174         return bool(_M_t);
175       }
177       constexpr const element_type* operator->() const
178       {
179         return get();
180       }
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       }
192       constexpr const element_type& operator*() const
193       {
194         return *get();
195       }
197       constexpr const element_type* get() const
198       {
199         return __to_raw_pointer(_M_t);
200       }
202       // [propagate_const.non_const_observers], non-const observers
203       constexpr element_type* operator->()
204       {
205         return get();
206       }
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       }
218       constexpr element_type& operator*()
219       {
220         return *get();
221       }
223       constexpr element_type* get()
224       {
225         return __to_raw_pointer(_M_t);
226       }
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       }
236     private:
237       _Tp _M_t;
238     };
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     }
248   template <typename _Tp>
249     constexpr bool
250     operator==(nullptr_t, const propagate_const<_Tp>& __pu)
251     {
252       return nullptr == get_underlying(__pu);
253     }
255   template <typename _Tp>
256     constexpr bool
257     operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
258     {
259       return get_underlying(__pt) != nullptr;
260     }
262   template <typename _Tp>
263     constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu)
264     {
265       return nullptr != get_underlying(__pu);
266     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
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     }
417   template <typename _Tp>
418     constexpr _Tp&
419     get_underlying(propagate_const<_Tp>& __pt) noexcept
420     {
421       return __pt._M_t;
422     }
424   // @} group propagate_const
425   _GLIBCXX_END_NAMESPACE_VERSION
426 } // namespace fundamentals_v2
427 } // namespace experimental
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>;
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    };
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      }
455      typedef experimental::propagate_const<_Tp> first_argument_type;
456      typedef experimental::propagate_const<_Tp> second_argument_type;
457      typedef bool result_type;
458    };
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      }
470      typedef experimental::propagate_const<_Tp> first_argument_type;
471      typedef experimental::propagate_const<_Tp> second_argument_type;
472      typedef bool result_type;
473    };
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      }
485      typedef experimental::propagate_const<_Tp> first_argument_type;
486      typedef experimental::propagate_const<_Tp> second_argument_type;
487      typedef bool result_type;
488    };
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      }
500      typedef experimental::propagate_const<_Tp> first_argument_type;
501      typedef experimental::propagate_const<_Tp> second_argument_type;
502      typedef bool result_type;
503    };
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      }
515      typedef experimental::propagate_const<_Tp> first_argument_type;
516      typedef experimental::propagate_const<_Tp> second_argument_type;
517      typedef bool result_type;
518    };
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      }
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
536 #endif // C++14
538 #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST