// -*- C++ -*- // Copyright (C) 2015-2021 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the // terms of the GNU General Public License as published by the // Free Software Foundation; either version 3, or (at your option) // any later version. // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // Under Section 7 of GPL version 3, you are granted additional // permissions described in the GCC Runtime Library Exception, version // 3.1, as published by the Free Software Foundation. // You should have received a copy of the GNU General Public License and // a copy of the GCC Runtime Library Exception along with this program; // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . /** @file experimental/propagate_const * This is a TS C++ Library header. * @ingroup libfund-ts */ #ifndef _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST #define _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 1 #pragma GCC system_header #if __cplusplus >= 201402L #include #include #include #include #include namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace experimental { inline namespace fundamentals_v2 { /** * @defgroup propagate_const Const-propagating wrapper * @ingroup libfund-ts * * A const-propagating wrapper that propagates const to pointer-like members, * as described in n4388 "A Proposal to Add a Const-Propagating Wrapper * to the Standard Library". * * @{ */ /// Const-propagating wrapper. template class propagate_const { public: typedef remove_reference_t())> element_type; private: template struct __is_propagate_const : false_type { }; template struct __is_propagate_const> : true_type { }; template friend constexpr const _Up& get_underlying(const propagate_const<_Up>& __pt) noexcept; template friend constexpr _Up& get_underlying(propagate_const<_Up>& __pt) noexcept; template static constexpr element_type* __to_raw_pointer(_Up* __u) { return __u; } template static constexpr element_type* __to_raw_pointer(_Up& __u) { return __u.get(); } template static constexpr const element_type* __to_raw_pointer(const _Up* __u) { return __u; } template static constexpr const element_type* __to_raw_pointer(const _Up& __u) { return __u.get(); } public: static_assert(__and_::type>, __not_>, __or_, is_pointer<_Tp>>>::value, "propagate_const requires a class or a pointer to an" " object type"); // [propagate_const.ctor], constructors constexpr propagate_const() = default; propagate_const(const propagate_const& __p) = delete; constexpr propagate_const(propagate_const&& __p) = default; template , is_convertible<_Up&&, _Tp>>::value, bool >::type=true> constexpr propagate_const(propagate_const<_Up>&& __pu) : _M_t(std::move(get_underlying(__pu))) {} template , __not_>>::value, bool>::type=false> constexpr explicit propagate_const(propagate_const<_Up>&& __pu) : _M_t(std::move(get_underlying(__pu))) {} template , is_convertible<_Up&&, _Tp>, __not_<__is_propagate_const< typename decay<_Up>::type>> >::value, bool>::type=true> constexpr propagate_const(_Up&& __u) : _M_t(std::forward<_Up>(__u)) {} template , __not_>, __not_<__is_propagate_const< typename decay<_Up>::type>> >::value, bool>::type=false> constexpr explicit propagate_const(_Up&& __u) : _M_t(std::forward<_Up>(__u)) {} // [propagate_const.assignment], assignment propagate_const& operator=(const propagate_const& __p) = delete; constexpr propagate_const& operator=(propagate_const&& __p) = default; template ::value>::type> constexpr propagate_const& operator=(propagate_const<_Up>&& __pu) { _M_t = std::move(get_underlying(__pu)); return *this; } template , __not_<__is_propagate_const< typename decay<_Up>::type>> >::value>::type> constexpr propagate_const& operator=(_Up&& __u) { _M_t = std::forward<_Up>(__u); return *this; } // [propagate_const.const_observers], const observers explicit constexpr operator bool() const { return bool(_M_t); } constexpr const element_type* operator->() const { return get(); } template , is_convertible<_Up, const element_type*> >::value, bool>::type = true> constexpr operator const element_type*() const { return get(); } constexpr const element_type& operator*() const { return *get(); } constexpr const element_type* get() const { return __to_raw_pointer(_M_t); } // [propagate_const.non_const_observers], non-const observers constexpr element_type* operator->() { return get(); } template , is_convertible<_Up, const element_type*> >::value, bool>::type = true> constexpr operator element_type*() { return get(); } constexpr element_type& operator*() { return *get(); } constexpr element_type* get() { return __to_raw_pointer(_M_t); } // [propagate_const.modifiers], modifiers constexpr void swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value) { using std::swap; swap(_M_t, get_underlying(__pt)); } private: _Tp _M_t; }; // [propagate_const.relational], relational operators template constexpr bool operator==(const propagate_const<_Tp>& __pt, nullptr_t) { return get_underlying(__pt) == nullptr; } template constexpr bool operator==(nullptr_t, const propagate_const<_Tp>& __pu) { return nullptr == get_underlying(__pu); } template constexpr bool operator!=(const propagate_const<_Tp>& __pt, nullptr_t) { return get_underlying(__pt) != nullptr; } template constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu) { return nullptr != get_underlying(__pu); } template constexpr bool operator==(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { return get_underlying(__pt) == get_underlying(__pu); } template constexpr bool operator!=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { return get_underlying(__pt) != get_underlying(__pu); } template constexpr bool operator<(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { return get_underlying(__pt) < get_underlying(__pu); } template constexpr bool operator>(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { return get_underlying(__pt) > get_underlying(__pu); } template constexpr bool operator<=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { return get_underlying(__pt) <= get_underlying(__pu); } template constexpr bool operator>=(const propagate_const<_Tp>& __pt, const propagate_const<_Up>& __pu) { return get_underlying(__pt) >= get_underlying(__pu); } template constexpr bool operator==(const propagate_const<_Tp>& __pt, const _Up& __u) { return get_underlying(__pt) == __u; } template constexpr bool operator!=(const propagate_const<_Tp>& __pt, const _Up& __u) { return get_underlying(__pt) != __u; } template constexpr bool operator<(const propagate_const<_Tp>& __pt, const _Up& __u) { return get_underlying(__pt) < __u; } template constexpr bool operator>(const propagate_const<_Tp>& __pt, const _Up& __u) { return get_underlying(__pt) > __u; } template constexpr bool operator<=(const propagate_const<_Tp>& __pt, const _Up& __u) { return get_underlying(__pt) <= __u; } template constexpr bool operator>=(const propagate_const<_Tp>& __pt, const _Up& __u) { return get_underlying(__pt) >= __u; } template constexpr bool operator==(const _Tp& __t, const propagate_const<_Up>& __pu) { return __t == get_underlying(__pu); } template constexpr bool operator!=(const _Tp& __t, const propagate_const<_Up>& __pu) { return __t != get_underlying(__pu); } template constexpr bool operator<(const _Tp& __t, const propagate_const<_Up>& __pu) { return __t < get_underlying(__pu); } template constexpr bool operator>(const _Tp& __t, const propagate_const<_Up>& __pu) { return __t > get_underlying(__pu); } template constexpr bool operator<=(const _Tp& __t, const propagate_const<_Up>& __pu) { return __t <= get_underlying(__pu); } template constexpr bool operator>=(const _Tp& __t, const propagate_const<_Up>& __pu) { return __t >= get_underlying(__pu); } // [propagate_const.algorithms], specialized algorithms // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3413. propagate_const's swap [...] needs to be constrained and use a trait template constexpr enable_if_t<__is_swappable<_Tp>::value, void> swap(propagate_const<_Tp>& __pt, propagate_const<_Tp>& __pt2) noexcept(__is_nothrow_swappable<_Tp>::value) { __pt.swap(__pt2); } // [propagate_const.underlying], underlying pointer access template constexpr const _Tp& get_underlying(const propagate_const<_Tp>& __pt) noexcept { return __pt._M_t; } template constexpr _Tp& get_underlying(propagate_const<_Tp>& __pt) noexcept { return __pt._M_t; } /// @} group propagate_const } // namespace fundamentals_v2 } // namespace experimental // [propagate_const.hash], hash support template struct hash> { using result_type = size_t; using argument_type = experimental::propagate_const<_Tp>; size_t operator()(const experimental::propagate_const<_Tp>& __t) const noexcept(noexcept(hash<_Tp>{}(get_underlying(__t)))) { return hash<_Tp>{}(get_underlying(__t)); } }; // [propagate_const.comparison_function_objects], comparison function objects template struct equal_to> { constexpr bool operator()(const experimental::propagate_const<_Tp>& __x, const experimental::propagate_const<_Tp>& __y) const { return equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y)); } typedef experimental::propagate_const<_Tp> first_argument_type; typedef experimental::propagate_const<_Tp> second_argument_type; typedef bool result_type; }; template struct not_equal_to> { constexpr bool operator()(const experimental::propagate_const<_Tp>& __x, const experimental::propagate_const<_Tp>& __y) const { return not_equal_to<_Tp>{}(get_underlying(__x), get_underlying(__y)); } typedef experimental::propagate_const<_Tp> first_argument_type; typedef experimental::propagate_const<_Tp> second_argument_type; typedef bool result_type; }; template struct less> { constexpr bool operator()(const experimental::propagate_const<_Tp>& __x, const experimental::propagate_const<_Tp>& __y) const { return less<_Tp>{}(get_underlying(__x), get_underlying(__y)); } typedef experimental::propagate_const<_Tp> first_argument_type; typedef experimental::propagate_const<_Tp> second_argument_type; typedef bool result_type; }; template struct greater> { constexpr bool operator()(const experimental::propagate_const<_Tp>& __x, const experimental::propagate_const<_Tp>& __y) const { return greater<_Tp>{}(get_underlying(__x), get_underlying(__y)); } typedef experimental::propagate_const<_Tp> first_argument_type; typedef experimental::propagate_const<_Tp> second_argument_type; typedef bool result_type; }; template struct less_equal> { constexpr bool operator()(const experimental::propagate_const<_Tp>& __x, const experimental::propagate_const<_Tp>& __y) const { return less_equal<_Tp>{}(get_underlying(__x), get_underlying(__y)); } typedef experimental::propagate_const<_Tp> first_argument_type; typedef experimental::propagate_const<_Tp> second_argument_type; typedef bool result_type; }; template struct greater_equal> { constexpr bool operator()(const experimental::propagate_const<_Tp>& __x, const experimental::propagate_const<_Tp>& __y) const { return greater_equal<_Tp>{}(get_underlying(__x), get_underlying(__y)); } typedef experimental::propagate_const<_Tp> first_argument_type; typedef experimental::propagate_const<_Tp> second_argument_type; typedef bool result_type; }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // C++14 #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST