/*============================================================================= Copyright (c) 2011-2019 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_MEMORY_EXEMPT_PTR_HPP #define SPROUT_MEMORY_EXEMPT_PTR_HPP #include #include #include #include #include #include #include #include #include #include #include #include namespace sprout { // // exempt_ptr // template class exempt_ptr { public: typedef T value_type; typedef T element_type; typedef T* pointer; typedef T const* const_pointer; typedef T& reference; typedef T const& const_reference; typedef std::ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; private: pointer p_; private: template static SPROUT_CONSTEXPR bool is_compat() { return std::is_convertible::value; } public: SPROUT_CONSTEXPR exempt_ptr() SPROUT_NOEXCEPT : p_() {} SPROUT_CONSTEXPR exempt_ptr(std::nullptr_t) SPROUT_NOEXCEPT : exempt_ptr() {} explicit SPROUT_CONSTEXPR exempt_ptr(pointer other) SPROUT_NOEXCEPT : p_(other) {} template< typename U, typename sprout::enabler_if::value>::type = sprout::enabler > explicit SPROUT_CONSTEXPR exempt_ptr(U* other) SPROUT_NOEXCEPT : p_(other) {} template< typename U, typename sprout::enabler_if::value>::type = sprout::enabler > SPROUT_CONSTEXPR exempt_ptr(sprout::exempt_ptr const& other) SPROUT_NOEXCEPT : p_(other.get()) {} SPROUT_CXX14_CONSTEXPR exempt_ptr& operator=(std::nullptr_t) SPROUT_NOEXCEPT { reset(); return *this; } template< typename U, typename sprout::enabler_if::value>::type = sprout::enabler > SPROUT_CXX14_CONSTEXPR exempt_ptr& operator=(U* other) SPROUT_NOEXCEPT { reset(other); return *this; } template< typename U, typename sprout::enabler_if::value>::type = sprout::enabler > SPROUT_CXX14_CONSTEXPR exempt_ptr& operator=(exempt_ptr const& other) SPROUT_NOEXCEPT { reset(other.get()); return *this; } SPROUT_CONSTEXPR pointer get() const SPROUT_NOEXCEPT { return p_; } SPROUT_CONSTEXPR reference operator*() const SPROUT_NOEXCEPT { return *get(); } SPROUT_CONSTEXPR pointer operator->() const SPROUT_NOEXCEPT { return get(); } SPROUT_EXPLICIT_CONVERSION SPROUT_CONSTEXPR operator bool() const SPROUT_NOEXCEPT { return get(); } SPROUT_EXPLICIT_CONVERSION SPROUT_CONSTEXPR operator pointer() const SPROUT_NOEXCEPT { return get(); } SPROUT_CXX14_CONSTEXPR pointer release() SPROUT_NOEXCEPT { pointer old = get(); reset(); return old; } SPROUT_CXX14_CONSTEXPR void reset(pointer t = 0) SPROUT_NOEXCEPT { p_ = t; } SPROUT_CXX14_CONSTEXPR void swap(exempt_ptr& other) SPROUT_NOEXCEPT { swap(p_, other.p_); } SPROUT_CXX14_CONSTEXPR exempt_ptr& operator++() { ++p_; return *this; } SPROUT_CXX14_CONSTEXPR exempt_ptr& operator--() { --p_; return *this; } SPROUT_CXX14_CONSTEXPR exempt_ptr operator++(int) { pointer tmp = p_; ++p_; return exempt_ptr{tmp}; } SPROUT_CXX14_CONSTEXPR exempt_ptr operator--(int) { pointer tmp = p_; --p_; return exempt_ptr{tmp}; } SPROUT_CXX14_CONSTEXPR exempt_ptr operator+() const { return *this; } SPROUT_CXX14_CONSTEXPR exempt_ptr operator+(std::ptrdiff_t d) const { return exempt_ptr{p_+d}; } SPROUT_CXX14_CONSTEXPR exempt_ptr operator-(std::ptrdiff_t d) const { return exempt_ptr{p_-d}; } SPROUT_CXX14_CONSTEXPR value_type& operator[](std::ptrdiff_t k) { return p_[k]; } SPROUT_CXX14_CONSTEXPR value_type const& operator[](std::ptrdiff_t k) const { return p_[k]; } }; // // swap // template inline SPROUT_CXX14_CONSTEXPR void swap(sprout::exempt_ptr& x, sprout::exempt_ptr& y) SPROUT_NOEXCEPT { x.swap(y); } // // make_exempt // template inline SPROUT_CONSTEXPR sprout::exempt_ptr make_exempt(T* p) SPROUT_NOEXCEPT { return sprout::exempt_ptr(p); } // // operator== // operator!= // template inline SPROUT_CONSTEXPR bool operator==(sprout::exempt_ptr const& x, sprout::exempt_ptr const& y) SPROUT_NOEXCEPT { return x.get() == y.get(); } template inline SPROUT_CONSTEXPR bool operator!=(sprout::exempt_ptr const& x, sprout::exempt_ptr const& y) SPROUT_NOEXCEPT { return !(x == y); } template inline SPROUT_CONSTEXPR bool operator==(sprout::exempt_ptr const& x, std::nullptr_t) SPROUT_NOEXCEPT { return !x; } template inline SPROUT_CONSTEXPR bool operator!=(sprout::exempt_ptr const& x, std::nullptr_t) SPROUT_NOEXCEPT { return static_cast(x); } template inline SPROUT_CONSTEXPR bool operator==(std::nullptr_t, sprout::exempt_ptr const& y) SPROUT_NOEXCEPT { return !y; } template inline SPROUT_CONSTEXPR bool operator!=(std::nullptr_t, sprout::exempt_ptr const& y) SPROUT_NOEXCEPT { return static_cast(y); } // // operator< // operator> // operator=< // operator=> // template inline SPROUT_CONSTEXPR bool operator<(sprout::exempt_ptr const& x, sprout::exempt_ptr const& y) { typedef typename sprout::common_decay::type type; return sprout::less()(x.get(), y.get()); } template inline SPROUT_CONSTEXPR bool operator>(sprout::exempt_ptr const& x, sprout::exempt_ptr const& y) { return y < x; } template inline SPROUT_CONSTEXPR bool operator<=(sprout::exempt_ptr const& x, sprout::exempt_ptr const& y) { return !(y < x); } template inline SPROUT_CONSTEXPR bool operator>=(sprout::exempt_ptr const& x, sprout::exempt_ptr const& y) { return !(x < y); } template inline SPROUT_CONSTEXPR bool operator<(sprout::exempt_ptr const& x, std::nullptr_t y) { return sprout::less()(x.get(), y); } template inline SPROUT_CONSTEXPR bool operator>(sprout::exempt_ptr const& x, std::nullptr_t y) { return y < x; } template inline SPROUT_CONSTEXPR bool operator<=(sprout::exempt_ptr const& x, std::nullptr_t y) { return !(y < x); } template inline SPROUT_CONSTEXPR bool operator>=(sprout::exempt_ptr const& x, std::nullptr_t y) { return !(x < y); } template inline SPROUT_CONSTEXPR bool operator<(std::nullptr_t x, sprout::exempt_ptr const& y) { return sprout::less()(x, y.get()); } template inline SPROUT_CONSTEXPR bool operator>(std::nullptr_t x, sprout::exempt_ptr const& y) { return y < x; } template inline SPROUT_CONSTEXPR bool operator<=(std::nullptr_t x, sprout::exempt_ptr const& y) { return !(y < x); } template inline SPROUT_CONSTEXPR bool operator>=(std::nullptr_t x, sprout::exempt_ptr const& y) { return !(x < y); } // // operator+ // operator- // template inline SPROUT_CONSTEXPR sprout::exempt_ptr operator+(std::ptrdiff_t d, sprout::exempt_ptr const& p) { return p + d; } template inline SPROUT_CONSTEXPR std::ptrdiff_t operator-(sprout::exempt_ptr const& x, sprout::exempt_ptr const& y) { return x.get() - y.get(); } // // operator<< // template inline SPROUT_CONSTEXPR std::basic_ostream& operator<<(std::basic_ostream& lhs, sprout::exempt_ptr const& rhs) { return lhs << rhs.get(); } } // namespace sprout namespace sprout { // // hash_value // template inline SPROUT_CONSTEXPR std::size_t hash_value(sprout::exempt_ptr const& v) { return sprout::hash_value(v.get()); } } // namespace sprout namespace std { #if defined(__clang__) # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wmismatched-tags" #endif // // hash // template struct hash > : public sprout::hash > {}; #if defined(__clang__) # pragma clang diagnostic pop #endif } // namespace std namespace sprout { // // static_pointer_cast // const_pointer_cast // dynamic_pointer_cast // reinterpret_pointer_cast // template inline SPROUT_CONSTEXPR sprout::exempt_ptr static_pointer_cast(sprout::exempt_ptr const& p) { typedef typename sprout::exempt_ptr::element_type element_type; return sprout::exempt_ptr(sprout::static_pointer_cast(p.get())); } template inline SPROUT_CONSTEXPR sprout::exempt_ptr const_pointer_cast(sprout::exempt_ptr const& p) { typedef typename sprout::exempt_ptr::element_type element_type; return sprout::exempt_ptr(sprout::const_pointer_cast(p.get())); } template inline SPROUT_CONSTEXPR sprout::exempt_ptr dynamic_pointer_cast(sprout::exempt_ptr const& p) { typedef typename sprout::exempt_ptr::element_type element_type; return sprout::exempt_ptr(sprout::dynamic_pointer_cast(p.get())); } template inline SPROUT_CONSTEXPR sprout::exempt_ptr reinterpret_pointer_cast(sprout::exempt_ptr const& p) { typedef typename sprout::exempt_ptr::element_type element_type; return sprout::exempt_ptr(sprout::reinterpret_pointer_cast(p.get())); } // // get_pointer // template inline SPROUT_NON_CONSTEXPR T* get_pointer(sprout::exempt_ptr const& p) SPROUT_NOEXCEPT { return p.get(); } } // namespace sprout #endif // #ifndef SPROUT_MEMORY_EXEMPT_PTR_HPP