* doc/xml/manual/status_cxx2017.xml: Update status table.
[official-gcc.git] / libstdc++-v3 / include / experimental / propagate_const
blobf90395964f77f069355c5f32afa5539e112d8605
1 // <experimental/propagate_const> -*- C++ -*-
3 // Copyright (C) 2015 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 <functional>
41 namespace std _GLIBCXX_VISIBILITY(default)
43 namespace experimental
45 inline namespace fundamentals_v2
47 _GLIBCXX_BEGIN_NAMESPACE_VERSION
49   /**
50    * @defgroup propagate_const Const-propagating wrapper
51    * @ingroup experimental
52    *
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".
56    *
57    * @{
58    */
60 /// Const-propagating wrapper.
61   template <typename _Tp>
62     class propagate_const
63     {
64     public:
65       typedef remove_reference_t<decltype(*declval<_Tp&>())> element_type;
67     private:
68       template <typename _Up>
69         struct __is_propagate_const : false_type
70         { };
72       template <typename _Up>
73         struct __is_propagate_const<propagate_const<_Up>> : true_type
74         { };
76       template <typename _Up>
77         friend constexpr const _Up&
78         get_underlying(const propagate_const<_Up>& __pt) noexcept;
79       template <typename _Up>
80         friend constexpr _Up&
81         get_underlying(propagate_const<_Up>& __pt) noexcept;
83       template <typename _Up>
84         static constexpr element_type*
85         __to_raw_pointer(_Up* __u)
86         { return __u; }
88       template <typename _Up>
89         static constexpr element_type*
90         __to_raw_pointer(_Up& __u)
91         { return __u.get(); }
93       template <typename _Up>
94         static constexpr const element_type*
95         __to_raw_pointer(const _Up* __u)
96         { return __u; }
98       template <typename _Up>
99         static constexpr const element_type*
100         __to_raw_pointer(const _Up& __u)
101         { return __u.get(); }
103     public:
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"
108                     " object type");
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
117                           >::type=true>
118       constexpr propagate_const(propagate_const<_Up>&& __pu)
119         : __t(move(get_underlying(__pu)))
120       {}
121       template <typename _Up, typename
122                 enable_if<__and_<is_constructible<_Tp, _Up&&>,
123                                  __not_<is_convertible<_Up&&, _Tp>>>::value,
124                           bool>::type=false>
125       constexpr explicit propagate_const(propagate_const<_Up>&& __pu)
126         : __t(move(get_underlying(__pu)))
127       {}
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))
136       {}
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))
145       {}
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)
154       {
155         __t = move(get_underlying(__pu));
156       }
158       template <typename _Up, typename =
159                 typename enable_if<__and_<is_convertible<_Up&&, _Tp>,
160                                           __not_<__is_propagate_const<
161                                                    typename decay<_Up>::type>>
162                                           >::value>::type>
163       constexpr propagate_const& operator=(_Up&& __u)
164       {
165         __t = forward<_Up>(__u);
166       }
168       // [propagate_const.const_observers], const observers
169       explicit constexpr operator bool() const
170       {
171         return bool(__t);
172       }
174       constexpr const element_type* operator->() const
175       {
176         return get();
177       }
179       template <typename _Up = _Tp,
180                 typename enable_if<__or_<is_pointer<_Up>,
181                                          is_convertible<_Up,
182                                                         const element_type*>
183                                          >::value, bool>::type = true>
184       constexpr operator const element_type*() const
185       {
186         return get();
187       }
189       constexpr const element_type& operator*() const
190       {
191         return *get();
192       }
194       constexpr const element_type* get() const
195       {
196         return __to_raw_pointer(__t);
197       }
199       // [propagate_const.non_const_observers], non-const observers
200       constexpr element_type* operator->()
201       {
202         return get();
203       }
205       template <typename _Up = _Tp,
206                 typename enable_if<__or_<is_pointer<_Up>,
207                                          is_convertible<_Up,
208                                                         const element_type*>
209                                          >::value, bool>::type = true>
210       constexpr operator element_type*()
211       {
212         return get();
213       }
215       constexpr element_type& operator*()
216       {
217         return *get();
218       }
220       constexpr element_type* get()
221       {
222         return __to_raw_pointer(__t);
223       }
225       // [propagate_const.modifiers], modifiers
226       constexpr void
227       swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value)
228       {
229         using std::swap;
230         swap(__t, get_underlying(__pt));
231       }
233     private:
234       _Tp __t; //exposition only
235     };
237   // [propagate_const.relational], relational operators
238   template <typename _Tp>
239     constexpr bool
240     operator==(const propagate_const<_Tp>& __pt, nullptr_t)
241     {
242       return get_underlying(__pt) == nullptr;
243     }
245   template <typename _Tp>
246     constexpr bool
247     operator==(nullptr_t, const propagate_const<_Tp>& __pu)
248     {
249       return nullptr == get_underlying(__pu);
250     }
252   template <typename _Tp>
253     constexpr bool
254     operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
255     {
256       return get_underlying(__pt) != nullptr;
257     }
259   template <typename _Tp>
260     constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu)
261     {
262       return nullptr != get_underlying(__pu);
263     }
265   template <typename _Tp, typename _Up>
266     constexpr bool
267     operator==(const propagate_const<_Tp>& __pt,
268                const propagate_const<_Up>& __pu)
269     {
270       return get_underlying(__pt) == get_underlying(__pu);
271     }
273   template <typename _Tp, typename _Up>
274     constexpr bool
275     operator!=(const propagate_const<_Tp>& __pt,
276                const propagate_const<_Up>& __pu)
277     {
278       return get_underlying(__pt) != get_underlying(__pu);
279     }
281   template <typename _Tp, typename _Up>
282     constexpr bool
283     operator<(const propagate_const<_Tp>& __pt,
284               const propagate_const<_Up>& __pu)
285     {
286       return get_underlying(__pt) < get_underlying(__pu);
287     }
289   template <typename _Tp, typename _Up>
290     constexpr bool
291     operator>(const propagate_const<_Tp>& __pt,
292               const propagate_const<_Up>& __pu)
293     {
294       return get_underlying(__pt) > get_underlying(__pu);
295     }
297   template <typename _Tp, typename _Up>
298     constexpr bool
299     operator<=(const propagate_const<_Tp>& __pt,
300                const propagate_const<_Up>& __pu)
301     {
302       return get_underlying(__pt) <= get_underlying(__pu);
303     }
305   template <typename _Tp, typename _Up>
306     constexpr bool
307     operator>=(const propagate_const<_Tp>& __pt,
308                const propagate_const<_Up>& __pu)
309     {
310       return get_underlying(__pt) >= get_underlying(__pu);
311     }
313   template <typename _Tp, typename _Up>
314     constexpr bool
315     operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
316     {
317       return get_underlying(__pt) == __u;
318     }
320   template <typename _Tp, typename _Up>
321     constexpr bool
322     operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
323     {
324       return get_underlying(__pt) != __u;
325     }
327   template <typename _Tp, typename _Up>
328     constexpr bool
329     operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
330     {
331       return get_underlying(__pt) < __u;
332     }
334   template <typename _Tp, typename _Up>
335     constexpr bool
336     operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
337     {
338       return get_underlying(__pt) > __u;
339     }
341   template <typename _Tp, typename _Up>
342     constexpr bool
343     operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
344     {
345       return get_underlying(__pt) <= __u;
346     }
348   template <typename _Tp, typename _Up>
349     constexpr bool
350     operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
351     {
352       return get_underlying(__pt) >= __u;
353     }
355   template <typename _Tp, typename _Up>
356     constexpr bool
357     operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
358     {
359       return __t == get_underlying(__pu);
360     }
362   template <typename _Tp, typename _Up>
363     constexpr bool
364     operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
365     {
366       return __t != get_underlying(__pu);
367     }
369   template <typename _Tp, typename _Up>
370     constexpr bool
371     operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
372     {
373       return __t < get_underlying(__pu);
374     }
376   template <typename _Tp, typename _Up>
377     constexpr bool
378     operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
379     {
380       return __t > get_underlying(__pu);
381     }
383   template <typename _Tp, typename _Up>
384     constexpr bool
385     operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
386     {
387       return __t <= get_underlying(__pu);
388     }
390   template <typename _Tp, typename _Up>
391     constexpr bool
392     operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
393     {
394       return __t >= get_underlying(__pu);
395     }
397   // [propagate_const.algorithms], specialized algorithms
398   template <typename _Tp>
399     constexpr void
400     swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2)
401       noexcept(__is_nothrow_swappable<_Tp>::value)
402     {
403       __pt.swap(__pt2);
404     }
406   // [propagate_const.underlying], underlying pointer access
407   template <typename _Tp>
408     constexpr const _Tp&
409     get_underlying(const propagate_const<_Tp>& __pt) noexcept
410     {
411       return __pt.__t;
412     }
414   template <typename _Tp>
415     constexpr _Tp&
416     get_underlying(propagate_const<_Tp>& __pt) noexcept
417     {
418       return __pt.__t;
419     }
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>>
429    {
430      using result_type = size_t;
431      using argument_type = experimental::propagate_const<_Tp>;
433      size_t
434      operator()(const experimental::propagate_const<_Tp>& __t) const
435      noexcept(noexcept(hash<_Tp>{}(get_underlying(__t))))
436      {
437        return hash<_Tp>{}(get_underlying(__t));
438      }
439    };
441  // [propagate_const.comparison_function_objects], comparison function objects
442  template <typename _Tp>
443    struct equal_to<experimental::propagate_const<_Tp>>
444    {
445      constexpr bool
446      operator()(const experimental::propagate_const<_Tp>& __x,
447                 const experimental::propagate_const<_Tp>& __y) const
448      {
449        return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
450      }
452      typedef experimental::propagate_const<_Tp> first_argument_type;
453      typedef experimental::propagate_const<_Tp> second_argument_type;
454      typedef bool result_type;
455    };
457  template <typename _Tp>
458    struct not_equal_to<experimental::propagate_const<_Tp>>
459    {
460      constexpr bool
461      operator()(const experimental::propagate_const<_Tp>& __x,
462                 const experimental::propagate_const<_Tp>& __y) const
463      {
464        return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
465      }
467      typedef experimental::propagate_const<_Tp> first_argument_type;
468      typedef experimental::propagate_const<_Tp> second_argument_type;
469      typedef bool result_type;
470    };
472  template <typename _Tp>
473    struct less<experimental::propagate_const<_Tp>>
474    {
475      constexpr bool
476      operator()(const experimental::propagate_const<_Tp>& __x,
477                 const experimental::propagate_const<_Tp>& __y) const
478      {
479        return less<_Tp>{}(get_underlying(__x), get_underlying(__y));
480      }
482      typedef experimental::propagate_const<_Tp> first_argument_type;
483      typedef experimental::propagate_const<_Tp> second_argument_type;
484      typedef bool result_type;
485    };
487  template <typename _Tp>
488    struct greater<experimental::propagate_const<_Tp>>
489    {
490      constexpr bool
491      operator()(const experimental::propagate_const<_Tp>& __x,
492                 const experimental::propagate_const<_Tp>& __y) const
493      {
494        return greater<_Tp>{}(get_underlying(__x), get_underlying(__y));
495      }
497      typedef experimental::propagate_const<_Tp> first_argument_type;
498      typedef experimental::propagate_const<_Tp> second_argument_type;
499      typedef bool result_type;
500    };
502  template <typename _Tp>
503    struct less_equal<experimental::propagate_const<_Tp>>
504    {
505      constexpr bool
506      operator()(const experimental::propagate_const<_Tp>& __x,
507                 const experimental::propagate_const<_Tp>& __y) const
508      {
509        return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
510      }
512      typedef experimental::propagate_const<_Tp> first_argument_type;
513      typedef experimental::propagate_const<_Tp> second_argument_type;
514      typedef bool result_type;
515    };
517  template <typename _Tp>
518    struct greater_equal<experimental::propagate_const<_Tp>>
519    {
520      constexpr bool
521      operator()(const experimental::propagate_const<_Tp>& __x,
522                 const experimental::propagate_const<_Tp>& __y) const
523      {
524        return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
525      }
527      typedef experimental::propagate_const<_Tp> first_argument_type;
528      typedef experimental::propagate_const<_Tp> second_argument_type;
529      typedef bool result_type;
530    };
531 } // namespace std
533 #endif // C++14
535 #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST