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