| // <experimental/propagate_const> -*- C++ -*- | |
| // Copyright (C) 2015-2019 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 | |
| // <http://www.gnu.org/licenses/>. | |
| /** @file experimental/propagate_const | |
| * This is a TS C++ Library header. | |
| */ | |
| #ifndef _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST | |
| #define _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST 1 | |
| #pragma GCC system_header | |
| #if __cplusplus >= 201402L | |
| #include <type_traits> | |
| #include <bits/functional_hash.h> | |
| #include <bits/move.h> | |
| #include <bits/stl_function.h> | |
| #include <experimental/bits/lfts_config.h> | |
| namespace std _GLIBCXX_VISIBILITY(default) | |
| { | |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
| namespace experimental | |
| { | |
| inline namespace fundamentals_v2 | |
| { | |
| /** | |
| * @defgroup propagate_const Const-propagating wrapper | |
| * @ingroup experimental | |
| * | |
| * 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 <typename _Tp> | |
| class propagate_const | |
| { | |
| public: | |
| typedef remove_reference_t<decltype(*std::declval<_Tp&>())> element_type; | |
| private: | |
| template <typename _Up> | |
| struct __is_propagate_const : false_type | |
| { }; | |
| template <typename _Up> | |
| struct __is_propagate_const<propagate_const<_Up>> : true_type | |
| { }; | |
| template <typename _Up> | |
| friend constexpr const _Up& | |
| get_underlying(const propagate_const<_Up>& __pt) noexcept; | |
| template <typename _Up> | |
| friend constexpr _Up& | |
| get_underlying(propagate_const<_Up>& __pt) noexcept; | |
| template <typename _Up> | |
| static constexpr element_type* | |
| __to_raw_pointer(_Up* __u) | |
| { return __u; } | |
| template <typename _Up> | |
| static constexpr element_type* | |
| __to_raw_pointer(_Up& __u) | |
| { return __u.get(); } | |
| template <typename _Up> | |
| static constexpr const element_type* | |
| __to_raw_pointer(const _Up* __u) | |
| { return __u; } | |
| template <typename _Up> | |
| static constexpr const element_type* | |
| __to_raw_pointer(const _Up& __u) | |
| { return __u.get(); } | |
| public: | |
| static_assert(__and_<is_object<typename remove_pointer<_Tp>::type>, | |
| __not_<is_array<_Tp>>, | |
| __or_<is_class<_Tp>, 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 <typename _Up, typename | |
| enable_if<__and_<is_constructible<_Tp, _Up&&>, | |
| is_convertible<_Up&&, _Tp>>::value, bool | |
| >::type=true> | |
| constexpr propagate_const(propagate_const<_Up>&& __pu) | |
| : _M_t(std::move(get_underlying(__pu))) | |
| {} | |
| template <typename _Up, typename | |
| enable_if<__and_<is_constructible<_Tp, _Up&&>, | |
| __not_<is_convertible<_Up&&, _Tp>>>::value, | |
| bool>::type=false> | |
| constexpr explicit propagate_const(propagate_const<_Up>&& __pu) | |
| : _M_t(std::move(get_underlying(__pu))) | |
| {} | |
| template <typename _Up, typename | |
| enable_if<__and_<is_constructible<_Tp, _Up&&>, | |
| 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 <typename _Up, typename | |
| enable_if<__and_<is_constructible<_Tp, _Up&&>, | |
| __not_<is_convertible<_Up&&, _Tp>>, | |
| __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 <typename _Up, typename = | |
| typename enable_if<is_convertible<_Up&&, _Tp>::value>::type> | |
| constexpr propagate_const& operator=(propagate_const<_Up>&& __pu) | |
| { | |
| _M_t = std::move(get_underlying(__pu)); | |
| return *this; | |
| } | |
| template <typename _Up, typename = | |
| typename enable_if<__and_<is_convertible<_Up&&, _Tp>, | |
| __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 <typename _Up = _Tp, | |
| typename enable_if<__or_<is_pointer<_Up>, | |
| 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 <typename _Up = _Tp, | |
| typename enable_if<__or_<is_pointer<_Up>, | |
| 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 <typename _Tp> | |
| constexpr bool | |
| operator==(const propagate_const<_Tp>& __pt, nullptr_t) | |
| { | |
| return get_underlying(__pt) == nullptr; | |
| } | |
| template <typename _Tp> | |
| constexpr bool | |
| operator==(nullptr_t, const propagate_const<_Tp>& __pu) | |
| { | |
| return nullptr == get_underlying(__pu); | |
| } | |
| template <typename _Tp> | |
| constexpr bool | |
| operator!=(const propagate_const<_Tp>& __pt, nullptr_t) | |
| { | |
| return get_underlying(__pt) != nullptr; | |
| } | |
| template <typename _Tp> | |
| constexpr bool operator!=(nullptr_t, const propagate_const<_Tp>& __pu) | |
| { | |
| return nullptr != get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator==(const propagate_const<_Tp>& __pt, | |
| const propagate_const<_Up>& __pu) | |
| { | |
| return get_underlying(__pt) == get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator!=(const propagate_const<_Tp>& __pt, | |
| const propagate_const<_Up>& __pu) | |
| { | |
| return get_underlying(__pt) != get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator<(const propagate_const<_Tp>& __pt, | |
| const propagate_const<_Up>& __pu) | |
| { | |
| return get_underlying(__pt) < get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator>(const propagate_const<_Tp>& __pt, | |
| const propagate_const<_Up>& __pu) | |
| { | |
| return get_underlying(__pt) > get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator<=(const propagate_const<_Tp>& __pt, | |
| const propagate_const<_Up>& __pu) | |
| { | |
| return get_underlying(__pt) <= get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator>=(const propagate_const<_Tp>& __pt, | |
| const propagate_const<_Up>& __pu) | |
| { | |
| return get_underlying(__pt) >= get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator==(const propagate_const<_Tp>& __pt, const _Up& __u) | |
| { | |
| return get_underlying(__pt) == __u; | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator!=(const propagate_const<_Tp>& __pt, const _Up& __u) | |
| { | |
| return get_underlying(__pt) != __u; | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator<(const propagate_const<_Tp>& __pt, const _Up& __u) | |
| { | |
| return get_underlying(__pt) < __u; | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator>(const propagate_const<_Tp>& __pt, const _Up& __u) | |
| { | |
| return get_underlying(__pt) > __u; | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator<=(const propagate_const<_Tp>& __pt, const _Up& __u) | |
| { | |
| return get_underlying(__pt) <= __u; | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator>=(const propagate_const<_Tp>& __pt, const _Up& __u) | |
| { | |
| return get_underlying(__pt) >= __u; | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator==(const _Tp& __t, const propagate_const<_Up>& __pu) | |
| { | |
| return __t == get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator!=(const _Tp& __t, const propagate_const<_Up>& __pu) | |
| { | |
| return __t != get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator<(const _Tp& __t, const propagate_const<_Up>& __pu) | |
| { | |
| return __t < get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator>(const _Tp& __t, const propagate_const<_Up>& __pu) | |
| { | |
| return __t > get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator<=(const _Tp& __t, const propagate_const<_Up>& __pu) | |
| { | |
| return __t <= get_underlying(__pu); | |
| } | |
| template <typename _Tp, typename _Up> | |
| constexpr bool | |
| operator>=(const _Tp& __t, const propagate_const<_Up>& __pu) | |
| { | |
| return __t >= get_underlying(__pu); | |
| } | |
| // [propagate_const.algorithms], specialized algorithms | |
| template <typename _Tp> | |
| constexpr 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 <typename _Tp> | |
| constexpr const _Tp& | |
| get_underlying(const propagate_const<_Tp>& __pt) noexcept | |
| { | |
| return __pt._M_t; | |
| } | |
| template <typename _Tp> | |
| 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 <typename _Tp> | |
| struct hash<experimental::propagate_const<_Tp>> | |
| { | |
| 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 <typename _Tp> | |
| struct equal_to<experimental::propagate_const<_Tp>> | |
| { | |
| 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 <typename _Tp> | |
| struct not_equal_to<experimental::propagate_const<_Tp>> | |
| { | |
| 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 <typename _Tp> | |
| struct less<experimental::propagate_const<_Tp>> | |
| { | |
| 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 <typename _Tp> | |
| struct greater<experimental::propagate_const<_Tp>> | |
| { | |
| 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 <typename _Tp> | |
| struct less_equal<experimental::propagate_const<_Tp>> | |
| { | |
| 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 <typename _Tp> | |
| struct greater_equal<experimental::propagate_const<_Tp>> | |
| { | |
| 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 |