| // <experimental/propagate_const> -*- C++ -*- |
| |
| // Copyright (C) 2015-2016 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 <= 201103L |
| # include <bits/c++14_warning.h> |
| #else |
| |
| #include <type_traits> |
| #include <functional> |
| |
| namespace std _GLIBCXX_VISIBILITY(default) |
| { |
| namespace experimental |
| { |
| inline namespace fundamentals_v2 |
| { |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION |
| |
| /** |
| * @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(*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) |
| : __t(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) |
| : __t(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) |
| : __t(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) |
| : __t(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) |
| { |
| __t = move(get_underlying(__pu)); |
| } |
| |
| 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) |
| { |
| __t = forward<_Up>(__u); |
| } |
| |
| // [propagate_const.const_observers], const observers |
| explicit constexpr operator bool() const |
| { |
| return bool(__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(__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(__t); |
| } |
| |
| // [propagate_const.modifiers], modifiers |
| constexpr void |
| swap(propagate_const& __pt) noexcept(__is_nothrow_swappable<_Tp>::value) |
| { |
| using std::swap; |
| swap(__t, get_underlying(__pt)); |
| } |
| |
| private: |
| _Tp __t; //exposition only |
| }; |
| |
| // [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.__t; |
| } |
| |
| template <typename _Tp> |
| constexpr _Tp& |
| get_underlying(propagate_const<_Tp>& __pt) noexcept |
| { |
| return __pt.__t; |
| } |
| |
| // @} group propagate_const |
| _GLIBCXX_END_NAMESPACE_VERSION |
| } // 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; |
| }; |
| } // namespace std |
| |
| #endif // C++14 |
| |
| #endif // _GLIBCXX_EXPERIMENTAL_PROPAGATE_CONST |