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