libstdc++
propagate_const
Go to the documentation of this file.
00001 // <experimental/propagate_const> -*- C++ -*-
00002 
00003 // Copyright (C) 2015-2017 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 3, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file experimental/propagate_const
00026  *  This is a TS C++ Library header.
00027  */
00028 
00029 #ifndef _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST
00030 #define _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 1
00031 
00032 #pragma GCC system_header
00033 
00034 #if __cplusplus <= 201103L
00035 # include <bits/c++14_warning.h>
00036 #else
00037 
00038 #include <type_traits>
00039 #include <bits/functional_hash.h>
00040 #include <bits/move.h>
00041 #include <bits/stl_function.h>
00042 #include <experimental/bits/lfts_config.h>
00043 
00044 namespace std _GLIBCXX_VISIBILITY(default)
00045 {
00046 namespace experimental
00047 {
00048 inline namespace fundamentals_v2
00049 {
00050 _GLIBCXX_BEGIN_NAMESPACE_VERSION
00051 
00052   /**
00053    * @defgroup propagate_const Const-propagating wrapper
00054    * @ingroup experimental
00055    *
00056    * A const-propagating wrapper that propagates const to pointer-like members,
00057    * as described in n4388 "A Proposal to Add a Const-Propagating Wrapper
00058    * to the Standard Library".
00059    *
00060    * @{
00061    */
00062 
00063 /// Const-propagating wrapper.
00064   template <typename _Tp>
00065     class propagate_const
00066     {
00067     public:
00068       typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type;
00069 
00070     private:
00071       template <typename _Up>
00072         struct __is_propagate_const : false_type
00073         { };
00074 
00075       template <typename _Up>
00076         struct __is_propagate_const<propagate_const<_Up>> : true_type
00077         { };
00078 
00079       template <typename _Up>
00080         friend constexpr const _Up&
00081         get_underlying(const propagate_const<_Up>& __pt) noexcept;
00082       template <typename _Up>
00083         friend constexpr _Up&
00084         get_underlying(propagate_const<_Up>& __pt) noexcept;
00085 
00086       template <typename _Up>
00087         static constexpr element_type*
00088         __to_raw_pointer(_Up* __u)
00089         { return __u; }
00090 
00091       template <typename _Up>
00092         static constexpr element_type*
00093         __to_raw_pointer(_Up& __u)
00094         { return __u.get(); }
00095 
00096       template <typename _Up>
00097         static constexpr const element_type*
00098         __to_raw_pointer(const _Up* __u)
00099         { return __u; }
00100 
00101       template <typename _Up>
00102         static constexpr const element_type*
00103         __to_raw_pointer(const _Up& __u)
00104         { return __u.get(); }
00105 
00106     public:
00107       static_assert(__and_<is_object<typename remove_pointer<_Tp>::type>,
00108                            __not_<is_array<_Tp>>,
00109                            __or_<is_class<_Tp>, is_pointer<_Tp>>>::value,
00110                     "propagate_const requires a class or a pointer to an"
00111                     " object type");
00112 
00113       // [propagate_const.ctor], constructors
00114       constexpr propagate_const() = default;
00115       propagate_const(const propagate_const& __p) = delete;
00116       constexpr propagate_const(propagate_const&& __p) = default;
00117       template <typename _Up, typename
00118                 enable_if<__and_<is_constructible<_Tp, _Up&&>,
00119                                  is_convertible<_Up&&, _Tp>>::value, bool
00120                           >::type=true>
00121       constexpr propagate_const(propagate_const<_Up>&& __pu)
00122         : _M_t(std::move(get_underlying(__pu)))
00123       {}
00124       template <typename _Up, typename
00125                 enable_if<__and_<is_constructible<_Tp, _Up&&>,
00126                                  __not_<is_convertible<_Up&&, _Tp>>>::value,
00127                           bool>::type=false>
00128       constexpr explicit propagate_const(propagate_const<_Up>&& __pu)
00129         : _M_t(std::move(get_underlying(__pu)))
00130       {}
00131       template <typename _Up, typename
00132                 enable_if<__and_<is_constructible<_Tp, _Up&&>,
00133                                  is_convertible<_Up&&, _Tp>,
00134                                  __not_<__is_propagate_const<
00135                                           typename decay<_Up>::type>>
00136                                  >::value, bool>::type=true>
00137       constexpr propagate_const(_Up&& __u)
00138         : _M_t(std::forward<_Up>(__u))
00139       {}
00140       template <typename _Up, typename
00141                 enable_if<__and_<is_constructible<_Tp, _Up&&>,
00142                                  __not_<is_convertible<_Up&&, _Tp>>,
00143                                  __not_<__is_propagate_const<
00144                                           typename decay<_Up>::type>>
00145                                  >::value, bool>::type=false>
00146       constexpr explicit propagate_const(_Up&& __u)
00147         : _M_t(std::forward<_Up>(__u))
00148       {}
00149 
00150       // [propagate_const.assignment], assignment
00151       propagate_const& operator=(const propagate_const& __p) = delete;
00152       constexpr propagate_const& operator=(propagate_const&& __p) = default;
00153 
00154       template <typename _Up, typename =
00155                 typename enable_if<is_convertible<_Up&&, _Tp>::value>::type>
00156       constexpr propagate_const& operator=(propagate_const<_Up>&& __pu)
00157       {
00158         _M_t = std::move(get_underlying(__pu));
00159         return *this;
00160       }
00161 
00162       template <typename _Up, typename =
00163                 typename enable_if<__and_<is_convertible<_Up&&, _Tp>,
00164                                           __not_<__is_propagate_const<
00165                                                    typename decay<_Up>::type>>
00166                                           >::value>::type>
00167       constexpr propagate_const& operator=(_Up&& __u)
00168       {
00169         _M_t = std::forward<_Up>(__u);
00170         return *this;
00171       }
00172 
00173       // [propagate_const.const_observers], const observers
00174       explicit constexpr operator bool() const
00175       {
00176         return bool(_M_t);
00177       }
00178 
00179       constexpr const element_type* operator->() const
00180       {
00181         return get();
00182       }
00183 
00184       template <typename _Up = _Tp,
00185                 typename enable_if<__or_<is_pointer<_Up>,
00186                                          is_convertible<_Up,
00187                                                         const element_type*>
00188                                          >::value, bool>::type = true>
00189       constexpr operator const element_type*() const
00190       {
00191         return get();
00192       }
00193 
00194       constexpr const element_type& operator*() const
00195       {
00196         return *get();
00197       }
00198 
00199       constexpr const element_type* get() const
00200       {
00201         return __to_raw_pointer(_M_t);
00202       }
00203 
00204       // [propagate_const.non_const_observers], non-const observers
00205       constexpr element_type* operator->()
00206       {
00207         return get();
00208       }
00209 
00210       template <typename _Up = _Tp,
00211                 typename enable_if<__or_<is_pointer<_Up>,
00212                                          is_convertible<_Up,
00213                                                         const element_type*>
00214                                          >::value, bool>::type = true>
00215       constexpr operator element_type*()
00216       {
00217         return get();
00218       }
00219 
00220       constexpr element_type& operator*()
00221       {
00222         return *get();
00223       }
00224 
00225       constexpr element_type* get()
00226       {
00227         return __to_raw_pointer(_M_t);
00228       }
00229 
00230       // [propagate_const.modifiers], modifiers
00231       constexpr void
00232       swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value)
00233       {
00234         using std::swap;
00235         swap(_M_t, get_underlying(__pt));
00236       }
00237 
00238     private:
00239       _Tp _M_t;
00240     };
00241 
00242   // [propagate_const.relational], relational operators
00243   template <typename _Tp>
00244     constexpr bool
00245     operator==(const propagate_const<_Tp>& __pt, nullptr_t)
00246     {
00247       return get_underlying(__pt) == nullptr;
00248     }
00249 
00250   template <typename _Tp>
00251     constexpr bool
00252     operator==(nullptr_t, const propagate_const<_Tp>& __pu)
00253     {
00254       return nullptr == get_underlying(__pu);
00255     }
00256 
00257   template <typename _Tp>
00258     constexpr bool
00259     operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
00260     {
00261       return get_underlying(__pt) != nullptr;
00262     }
00263 
00264   template <typename _Tp>
00265     constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu)
00266     {
00267       return nullptr != get_underlying(__pu);
00268     }
00269 
00270   template <typename _Tp, typename _Up>
00271     constexpr bool
00272     operator==(const propagate_const<_Tp>& __pt,
00273                const propagate_const<_Up>& __pu)
00274     {
00275       return get_underlying(__pt) == get_underlying(__pu);
00276     }
00277 
00278   template <typename _Tp, typename _Up>
00279     constexpr bool
00280     operator!=(const propagate_const<_Tp>& __pt,
00281                const propagate_const<_Up>& __pu)
00282     {
00283       return get_underlying(__pt) != get_underlying(__pu);
00284     }
00285 
00286   template <typename _Tp, typename _Up>
00287     constexpr bool
00288     operator<(const propagate_const<_Tp>& __pt,
00289               const propagate_const<_Up>& __pu)
00290     {
00291       return get_underlying(__pt) < get_underlying(__pu);
00292     }
00293 
00294   template <typename _Tp, typename _Up>
00295     constexpr bool
00296     operator>(const propagate_const<_Tp>& __pt,
00297               const propagate_const<_Up>& __pu)
00298     {
00299       return get_underlying(__pt) > get_underlying(__pu);
00300     }
00301 
00302   template <typename _Tp, typename _Up>
00303     constexpr bool
00304     operator<=(const propagate_const<_Tp>& __pt,
00305                const propagate_const<_Up>& __pu)
00306     {
00307       return get_underlying(__pt) <= get_underlying(__pu);
00308     }
00309 
00310   template <typename _Tp, typename _Up>
00311     constexpr bool
00312     operator>=(const propagate_const<_Tp>& __pt,
00313                const propagate_const<_Up>& __pu)
00314     {
00315       return get_underlying(__pt) >= get_underlying(__pu);
00316     }
00317 
00318   template <typename _Tp, typename _Up>
00319     constexpr bool
00320     operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
00321     {
00322       return get_underlying(__pt) == __u;
00323     }
00324 
00325   template <typename _Tp, typename _Up>
00326     constexpr bool
00327     operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
00328     {
00329       return get_underlying(__pt) != __u;
00330     }
00331 
00332   template <typename _Tp, typename _Up>
00333     constexpr bool
00334     operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
00335     {
00336       return get_underlying(__pt) < __u;
00337     }
00338 
00339   template <typename _Tp, typename _Up>
00340     constexpr bool
00341     operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
00342     {
00343       return get_underlying(__pt) > __u;
00344     }
00345 
00346   template <typename _Tp, typename _Up>
00347     constexpr bool
00348     operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
00349     {
00350       return get_underlying(__pt) <= __u;
00351     }
00352 
00353   template <typename _Tp, typename _Up>
00354     constexpr bool
00355     operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
00356     {
00357       return get_underlying(__pt) >= __u;
00358     }
00359 
00360   template <typename _Tp, typename _Up>
00361     constexpr bool
00362     operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
00363     {
00364       return __t == get_underlying(__pu);
00365     }
00366 
00367   template <typename _Tp, typename _Up>
00368     constexpr bool
00369     operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
00370     {
00371       return __t != get_underlying(__pu);
00372     }
00373 
00374   template <typename _Tp, typename _Up>
00375     constexpr bool
00376     operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
00377     {
00378       return __t < get_underlying(__pu);
00379     }
00380 
00381   template <typename _Tp, typename _Up>
00382     constexpr bool
00383     operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
00384     {
00385       return __t > get_underlying(__pu);
00386     }
00387 
00388   template <typename _Tp, typename _Up>
00389     constexpr bool
00390     operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
00391     {
00392       return __t <= get_underlying(__pu);
00393     }
00394 
00395   template <typename _Tp, typename _Up>
00396     constexpr bool
00397     operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
00398     {
00399       return __t >= get_underlying(__pu);
00400     }
00401 
00402   // [propagate_const.algorithms], specialized algorithms
00403   template <typename _Tp>
00404     constexpr void
00405     swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2)
00406       noexcept(__is_nothrow_swappable<_Tp>::value)
00407     {
00408       __pt.swap(__pt2);
00409     }
00410 
00411   // [propagate_const.underlying], underlying pointer access
00412   template <typename _Tp>
00413     constexpr const _Tp&
00414     get_underlying(const propagate_const<_Tp>& __pt) noexcept
00415     {
00416       return __pt._M_t;
00417     }
00418 
00419   template <typename _Tp>
00420     constexpr _Tp&
00421     get_underlying(propagate_const<_Tp>& __pt) noexcept
00422     {
00423       return __pt._M_t;
00424     }
00425 
00426   // @} group propagate_const
00427   _GLIBCXX_END_NAMESPACE_VERSION
00428 } // namespace fundamentals_v2
00429 } // namespace experimental
00430 
00431 // [propagate_const.hash], hash support
00432  template <typename _Tp>
00433    struct hash<experimental::propagate_const<_Tp>>
00434    {
00435      using result_type = size_t;
00436      using argument_type = experimental::propagate_const<_Tp>;
00437 
00438      size_t
00439      operator()(const experimental::propagate_const<_Tp>& __t) const
00440      noexcept(noexcept(hash<_Tp>{}(get_underlying(__t))))
00441      {
00442        return hash<_Tp>{}(get_underlying(__t));
00443      }
00444    };
00445 
00446  // [propagate_const.comparison_function_objects], comparison function objects
00447  template <typename _Tp>
00448    struct equal_to<experimental::propagate_const<_Tp>>
00449    {
00450      constexpr bool
00451      operator()(const experimental::propagate_const<_Tp>& __x,
00452                 const experimental::propagate_const<_Tp>& __y) const
00453      {
00454        return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
00455      }
00456 
00457      typedef experimental::propagate_const<_Tp> first_argument_type;
00458      typedef experimental::propagate_const<_Tp> second_argument_type;
00459      typedef bool result_type;
00460    };
00461 
00462  template <typename _Tp>
00463    struct not_equal_to<experimental::propagate_const<_Tp>>
00464    {
00465      constexpr bool
00466      operator()(const experimental::propagate_const<_Tp>& __x,
00467                 const experimental::propagate_const<_Tp>& __y) const
00468      {
00469        return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
00470      }
00471 
00472      typedef experimental::propagate_const<_Tp> first_argument_type;
00473      typedef experimental::propagate_const<_Tp> second_argument_type;
00474      typedef bool result_type;
00475    };
00476 
00477  template <typename _Tp>
00478    struct less<experimental::propagate_const<_Tp>>
00479    {
00480      constexpr bool
00481      operator()(const experimental::propagate_const<_Tp>& __x,
00482                 const experimental::propagate_const<_Tp>& __y) const
00483      {
00484        return less<_Tp>{}(get_underlying(__x), get_underlying(__y));
00485      }
00486 
00487      typedef experimental::propagate_const<_Tp> first_argument_type;
00488      typedef experimental::propagate_const<_Tp> second_argument_type;
00489      typedef bool result_type;
00490    };
00491 
00492  template <typename _Tp>
00493    struct greater<experimental::propagate_const<_Tp>>
00494    {
00495      constexpr bool
00496      operator()(const experimental::propagate_const<_Tp>& __x,
00497                 const experimental::propagate_const<_Tp>& __y) const
00498      {
00499        return greater<_Tp>{}(get_underlying(__x), get_underlying(__y));
00500      }
00501 
00502      typedef experimental::propagate_const<_Tp> first_argument_type;
00503      typedef experimental::propagate_const<_Tp> second_argument_type;
00504      typedef bool result_type;
00505    };
00506 
00507  template <typename _Tp>
00508    struct less_equal<experimental::propagate_const<_Tp>>
00509    {
00510      constexpr bool
00511      operator()(const experimental::propagate_const<_Tp>& __x,
00512                 const experimental::propagate_const<_Tp>& __y) const
00513      {
00514        return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
00515      }
00516 
00517      typedef experimental::propagate_const<_Tp> first_argument_type;
00518      typedef experimental::propagate_const<_Tp> second_argument_type;
00519      typedef bool result_type;
00520    };
00521 
00522  template <typename _Tp>
00523    struct greater_equal<experimental::propagate_const<_Tp>>
00524    {
00525      constexpr bool
00526      operator()(const experimental::propagate_const<_Tp>& __x,
00527                 const experimental::propagate_const<_Tp>& __y) const
00528      {
00529        return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
00530      }
00531 
00532      typedef experimental::propagate_const<_Tp> first_argument_type;
00533      typedef experimental::propagate_const<_Tp> second_argument_type;
00534      typedef bool result_type;
00535    };
00536 } // namespace std
00537 
00538 #endif // C++14
00539 
00540 #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST