관리-도구
편집 파일: propagate_const
// <experimental/propagate_const> -*- C++ -*- // Copyright (C) 2015-2018 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