1 // <experimental/propagate_const> -*- C++ -*-
     3 // Copyright (C) 2015-2016 Free Software Foundation, Inc.
     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)
    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.
    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>
    38 #include <type_traits>
    40 #include <experimental/bits/lfts_config.h>
    42 namespace std _GLIBCXX_VISIBILITY(default)
    44 namespace experimental
    46 inline namespace fundamentals_v2
    48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
    51    * @defgroup propagate_const Const-propagating wrapper
    52    * @ingroup experimental
    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".
    61 /// Const-propagating wrapper.
    62   template <typename _Tp>
    66       typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type;
    69       template <typename _Up>
    70    struct __is_propagate_const : false_type
    73       template <typename _Up>
    74    struct __is_propagate_const<propagate_const<_Up>> : true_type
    77       template <typename _Up>
    78    friend constexpr const _Up&
    79    get_underlying(const propagate_const<_Up>& __pt) noexcept;
    80       template <typename _Up>
    82    get_underlying(propagate_const<_Up>& __pt) noexcept;
    84       template <typename _Up>
    85    static constexpr element_type*
    86    __to_raw_pointer(_Up* __u)
    89       template <typename _Up>
    90    static constexpr element_type*
    91    __to_raw_pointer(_Up& __u)
    94       template <typename _Up>
    95    static constexpr const element_type*
    96    __to_raw_pointer(const _Up* __u)
    99       template <typename _Up>
   100    static constexpr const element_type*
   101    __to_raw_pointer(const _Up& __u)
   102    { return __u.get(); }
   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"
   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
   119       constexpr propagate_const(propagate_const<_Up>&& __pu)
   120    : _M_t(std::move(get_underlying(__pu)))
   122       template <typename _Up, typename
   123            enable_if<__and_<is_constructible<_Tp, _Up&&>,
   124                             __not_<is_convertible<_Up&&, _Tp>>>::value,
   126       constexpr explicit propagate_const(propagate_const<_Up>&& __pu)
   127    : _M_t(std::move(get_underlying(__pu)))
   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))
   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))
   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)
   156    _M_t = std::move(get_underlying(__pu));
   160       template <typename _Up, typename =
   161            typename enable_if<__and_<is_convertible<_Up&&, _Tp>,
   162                                      __not_<__is_propagate_const<
   163                                               typename decay<_Up>::type>>
   165       constexpr propagate_const& operator=(_Up&& __u)
   167    _M_t = std::forward<_Up>(__u);
   171       // [propagate_const.const_observers], const observers
   172       explicit constexpr operator bool() const
   177       constexpr const element_type* operator->() const
   182       template <typename _Up = _Tp,
   183            typename enable_if<__or_<is_pointer<_Up>,
   186                                     >::value, bool>::type = true>
   187       constexpr operator const element_type*() const
   192       constexpr const element_type& operator*() const
   197       constexpr const element_type* get() const
   199    return __to_raw_pointer(_M_t);
   202       // [propagate_const.non_const_observers], non-const observers
   203       constexpr element_type* operator->()
   208       template <typename _Up = _Tp,
   209            typename enable_if<__or_<is_pointer<_Up>,
   212                                     >::value, bool>::type = true>
   213       constexpr operator element_type*()
   218       constexpr element_type& operator*()
   223       constexpr element_type* get()
   225    return __to_raw_pointer(_M_t);
   228       // [propagate_const.modifiers], modifiers
   230       swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value)
   233    swap(_M_t, get_underlying(__pt));
   240   // [propagate_const.relational], relational operators
   241   template <typename _Tp>
   243     operator==(const propagate_const<_Tp>& __pt, nullptr_t)
   245       return get_underlying(__pt) == nullptr;
   248   template <typename _Tp>
   250     operator==(nullptr_t, const propagate_const<_Tp>& __pu)
   252       return nullptr == get_underlying(__pu);
   255   template <typename _Tp>
   257     operator!=(const propagate_const<_Tp>& __pt, nullptr_t)
   259       return get_underlying(__pt) != nullptr;
   262   template <typename _Tp>
   263     constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu)
   265       return nullptr != get_underlying(__pu);
   268   template <typename _Tp, typename _Up>
   270     operator==(const propagate_const<_Tp>& __pt,
   271           const propagate_const<_Up>& __pu)
   273       return get_underlying(__pt) == get_underlying(__pu);
   276   template <typename _Tp, typename _Up>
   278     operator!=(const propagate_const<_Tp>& __pt,
   279           const propagate_const<_Up>& __pu)
   281       return get_underlying(__pt) != get_underlying(__pu);
   284   template <typename _Tp, typename _Up>
   286     operator<(const propagate_const<_Tp>& __pt,
   287          const propagate_const<_Up>& __pu)
   289       return get_underlying(__pt) < get_underlying(__pu);
   292   template <typename _Tp, typename _Up>
   294     operator>(const propagate_const<_Tp>& __pt,
   295          const propagate_const<_Up>& __pu)
   297       return get_underlying(__pt) > get_underlying(__pu);
   300   template <typename _Tp, typename _Up>
   302     operator<=(const propagate_const<_Tp>& __pt,
   303           const propagate_const<_Up>& __pu)
   305       return get_underlying(__pt) <= get_underlying(__pu);
   308   template <typename _Tp, typename _Up>
   310     operator>=(const propagate_const<_Tp>& __pt,
   311           const propagate_const<_Up>& __pu)
   313       return get_underlying(__pt) >= get_underlying(__pu);
   316   template <typename _Tp, typename _Up>
   318     operator==(const propagate_const<_Tp>& __pt, const _Up& __u)
   320       return get_underlying(__pt) == __u;
   323   template <typename _Tp, typename _Up>
   325     operator!=(const propagate_const<_Tp>& __pt, const _Up& __u)
   327       return get_underlying(__pt) != __u;
   330   template <typename _Tp, typename _Up>
   332     operator<(const propagate_const<_Tp>& __pt, const _Up& __u)
   334       return get_underlying(__pt) < __u;
   337   template <typename _Tp, typename _Up>
   339     operator>(const propagate_const<_Tp>& __pt, const _Up& __u)
   341       return get_underlying(__pt) > __u;
   344   template <typename _Tp, typename _Up>
   346     operator<=(const propagate_const<_Tp>& __pt, const _Up& __u)
   348       return get_underlying(__pt) <= __u;
   351   template <typename _Tp, typename _Up>
   353     operator>=(const propagate_const<_Tp>& __pt, const _Up& __u)
   355       return get_underlying(__pt) >= __u;
   358   template <typename _Tp, typename _Up>
   360     operator==(const _Tp& __t, const propagate_const<_Up>& __pu)
   362       return __t == get_underlying(__pu);
   365   template <typename _Tp, typename _Up>
   367     operator!=(const _Tp& __t, const propagate_const<_Up>& __pu)
   369       return __t != get_underlying(__pu);
   372   template <typename _Tp, typename _Up>
   374     operator<(const _Tp& __t, const propagate_const<_Up>& __pu)
   376       return __t < get_underlying(__pu);
   379   template <typename _Tp, typename _Up>
   381     operator>(const _Tp& __t, const propagate_const<_Up>& __pu)
   383       return __t > get_underlying(__pu);
   386   template <typename _Tp, typename _Up>
   388     operator<=(const _Tp& __t, const propagate_const<_Up>& __pu)
   390       return __t <= get_underlying(__pu);
   393   template <typename _Tp, typename _Up>
   395     operator>=(const _Tp& __t, const propagate_const<_Up>& __pu)
   397       return __t >= get_underlying(__pu);
   400   // [propagate_const.algorithms], specialized algorithms
   401   template <typename _Tp>
   403     swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2)
   404       noexcept(__is_nothrow_swappable<_Tp>::value)
   409   // [propagate_const.underlying], underlying pointer access
   410   template <typename _Tp>
   412     get_underlying(const propagate_const<_Tp>& __pt) noexcept
   417   template <typename _Tp>
   419     get_underlying(propagate_const<_Tp>& __pt) noexcept
   424   // @} group propagate_const
   425   _GLIBCXX_END_NAMESPACE_VERSION
   426 } // namespace fundamentals_v2
   427 } // namespace experimental
   429 // [propagate_const.hash], hash support
   430  template <typename _Tp>
   431    struct hash<experimental::propagate_const<_Tp>>
   433      using result_type = size_t;
   434      using argument_type = experimental::propagate_const<_Tp>;
   437      operator()(const experimental::propagate_const<_Tp>& __t) const
   438      noexcept(noexcept(hash<_Tp>{}(get_underlying(__t))))
   440        return hash<_Tp>{}(get_underlying(__t));
   444  // [propagate_const.comparison_function_objects], comparison function objects
   445  template <typename _Tp>
   446    struct equal_to<experimental::propagate_const<_Tp>>
   449      operator()(const experimental::propagate_const<_Tp>& __x,
   450            const experimental::propagate_const<_Tp>& __y) const
   452        return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
   455      typedef experimental::propagate_const<_Tp> first_argument_type;
   456      typedef experimental::propagate_const<_Tp> second_argument_type;
   457      typedef bool result_type;
   460  template <typename _Tp>
   461    struct not_equal_to<experimental::propagate_const<_Tp>>
   464      operator()(const experimental::propagate_const<_Tp>& __x,
   465            const experimental::propagate_const<_Tp>& __y) const
   467        return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y));
   470      typedef experimental::propagate_const<_Tp> first_argument_type;
   471      typedef experimental::propagate_const<_Tp> second_argument_type;
   472      typedef bool result_type;
   475  template <typename _Tp>
   476    struct less<experimental::propagate_const<_Tp>>
   479      operator()(const experimental::propagate_const<_Tp>& __x,
   480            const experimental::propagate_const<_Tp>& __y) const
   482        return less<_Tp>{}(get_underlying(__x), get_underlying(__y));
   485      typedef experimental::propagate_const<_Tp> first_argument_type;
   486      typedef experimental::propagate_const<_Tp> second_argument_type;
   487      typedef bool result_type;
   490  template <typename _Tp>
   491    struct greater<experimental::propagate_const<_Tp>>
   494      operator()(const experimental::propagate_const<_Tp>& __x,
   495            const experimental::propagate_const<_Tp>& __y) const
   497        return greater<_Tp>{}(get_underlying(__x), get_underlying(__y));
   500      typedef experimental::propagate_const<_Tp> first_argument_type;
   501      typedef experimental::propagate_const<_Tp> second_argument_type;
   502      typedef bool result_type;
   505  template <typename _Tp>
   506    struct less_equal<experimental::propagate_const<_Tp>>
   509      operator()(const experimental::propagate_const<_Tp>& __x,
   510            const experimental::propagate_const<_Tp>& __y) const
   512        return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
   515      typedef experimental::propagate_const<_Tp> first_argument_type;
   516      typedef experimental::propagate_const<_Tp> second_argument_type;
   517      typedef bool result_type;
   520  template <typename _Tp>
   521    struct greater_equal<experimental::propagate_const<_Tp>>
   524      operator()(const experimental::propagate_const<_Tp>& __x,
   525            const experimental::propagate_const<_Tp>& __y) const
   527        return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y));
   530      typedef experimental::propagate_const<_Tp> first_argument_type;
   531      typedef experimental::propagate_const<_Tp> second_argument_type;
   532      typedef bool result_type;
   538 #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST