/cp
[official-gcc.git] / libstdc++-v3 / include / experimental / propagate_const
blob004f4e810564c45e1387991f4ebda2aec58dda9a
1 // <experimental/propagate_const> -*- C++ -*-
3 // Copyright (C) 2015-2018 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 >= 201402L
36 #include <type_traits>
37 #include <bits/functional_hash.h>
38 #include <bits/move.h>
39 #include <bits/stl_function.h>
40 #include <experimental/bits/lfts_config.h>
42 namespace std _GLIBCXX_VISIBILITY(default)
44 _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 namespace experimental
48 inline namespace fundamentals_v2
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    */
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;
68     private:
69       template <typename _Up>
70         struct __is_propagate_const : false_type
71         { };
73       template <typename _Up>
74         struct __is_propagate_const<propagate_const<_Up>> : true_type
75         { };
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;
84       template <typename _Up>
85         static constexpr element_type*
86         __to_raw_pointer(_Up* __u)
87         { return __u; }
89       template <typename _Up>
90         static constexpr element_type*
91         __to_raw_pointer(_Up& __u)
92         { return __u.get(); }
94       template <typename _Up>
95         static constexpr const element_type*
96         __to_raw_pointer(const _Up* __u)
97         { return __u; }
99       template <typename _Up>
100         static constexpr const element_type*
101         __to_raw_pointer(const _Up& __u)
102         { return __u.get(); }
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");
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       {}
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)
155       {
156         _M_t = std::move(get_underlying(__pu));
157         return *this;
158       }
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       }
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 } // namespace fundamentals_v2
426 } // namespace experimental
428 // [propagate_const.hash], hash support
429  template <typename _Tp>
430    struct hash<experimental::propagate_const<_Tp>>
431    {
432      using result_type = size_t;
433      using argument_type = experimental::propagate_const<_Tp>;
435      size_t
436      operator()(const experimental::propagate_const<_Tp>& __t) const
437      noexcept(noexcept(hash<_Tp>{}(get_underlying(__t))))
438      {
439        return hash<_Tp>{}(get_underlying(__t));
440      }
441    };
443  // [propagate_const.comparison_function_objects], comparison function objects
444  template <typename _Tp>
445    struct equal_to<experimental::propagate_const<_Tp>>
446    {
447      constexpr bool
448      operator()(const experimental::propagate_const<_Tp>& __x,
449                 const experimental::propagate_const<_Tp>& __y) const
450      {
451        return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
452      }
454      typedef experimental::propagate_const<_Tp> first_argument_type;
455      typedef experimental::propagate_const<_Tp> second_argument_type;
456      typedef bool result_type;
457    };
459  template <typename _Tp>
460    struct not_equal_to<experimental::propagate_const<_Tp>>
461    {
462      constexpr bool
463      operator()(const experimental::propagate_const<_Tp>& __x,
464                 const experimental::propagate_const<_Tp>& __y) const
465      {
466        return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
467      }
469      typedef experimental::propagate_const<_Tp> first_argument_type;
470      typedef experimental::propagate_const<_Tp> second_argument_type;
471      typedef bool result_type;
472    };
474  template <typename _Tp>
475    struct less<experimental::propagate_const<_Tp>>
476    {
477      constexpr bool
478      operator()(const experimental::propagate_const<_Tp>& __x,
479                 const experimental::propagate_const<_Tp>& __y) const
480      {
481        return less<_Tp>{}(get_underlying(__x), get_underlying(__y));
482      }
484      typedef experimental::propagate_const<_Tp> first_argument_type;
485      typedef experimental::propagate_const<_Tp> second_argument_type;
486      typedef bool result_type;
487    };
489  template <typename _Tp>
490    struct greater<experimental::propagate_const<_Tp>>
491    {
492      constexpr bool
493      operator()(const experimental::propagate_const<_Tp>& __x,
494                 const experimental::propagate_const<_Tp>& __y) const
495      {
496        return greater<_Tp>{}(get_underlying(__x), get_underlying(__y));
497      }
499      typedef experimental::propagate_const<_Tp> first_argument_type;
500      typedef experimental::propagate_const<_Tp> second_argument_type;
501      typedef bool result_type;
502    };
504  template <typename _Tp>
505    struct less_equal<experimental::propagate_const<_Tp>>
506    {
507      constexpr bool
508      operator()(const experimental::propagate_const<_Tp>& __x,
509                 const experimental::propagate_const<_Tp>& __y) const
510      {
511        return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
512      }
514      typedef experimental::propagate_const<_Tp> first_argument_type;
515      typedef experimental::propagate_const<_Tp> second_argument_type;
516      typedef bool result_type;
517    };
519  template <typename _Tp>
520    struct greater_equal<experimental::propagate_const<_Tp>>
521    {
522      constexpr bool
523      operator()(const experimental::propagate_const<_Tp>& __x,
524                 const experimental::propagate_const<_Tp>& __y) const
525      {
526        return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
527      }
529      typedef experimental::propagate_const<_Tp> first_argument_type;
530      typedef experimental::propagate_const<_Tp> second_argument_type;
531      typedef bool result_type;
532    };
534 _GLIBCXX_END_NAMESPACE_VERSION
535 } // namespace std
537 #endif // C++14
539 #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST