// Custom pointer adapter and sample storage policies
-// Copyright (C) 2008 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 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 2, or (at your option)
+// 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,
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License along
-// with this library; see the file COPYING. If not, write to the Free
-// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
-// USA.
+// 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.
-// As a special exception, you may use this file as part of a free software
-// library without restriction. Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License. This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
+// 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 ext/pointer.h
- * @author Bob Walters
+ * @file ext/pointer.h
+ * This file is a GNU extension to the Standard C++ Library.
+ *
+ * @author Bob Walters
*
* Provides reusable _Pointer_adapter for assisting in the development of
* custom pointer types that can be used with the standard containers via
#ifndef _POINTER_H
#define _POINTER_H 1
-#include <iosfwd>
+#pragma GCC system_header
+
+#if _GLIBCXX_HOSTED
+# include <iosfwd>
+#endif
+
#include <bits/stl_iterator_base_types.h>
#include <ext/cast.h>
-
-_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
+#include <ext/type_traits.h>
+#if __cplusplus >= 201103L
+# include <bits/move.h>
+# include <bits/ptr_traits.h>
+#endif
+#if __cplusplus > 201703L
+# include <iterator> // for indirectly_readable_traits
+#endif
+
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
/**
* @brief A storage policy for use with _Pointer_adapter<> which yields a
* the pointer's address as an offset value which is relative to
* its own address.
*
- * This is intended for pointers
- * within shared memory regions which might be mapped at different
- * addresses by different processes. For null pointers, a value of 1 is
- * used. (0 is legitimate sometimes for nodes in circularly linked lists)
- * This value was chosen as the least likely to generate an incorrect null,
- * As there is no reason why any normal pointer would point 1 byte into
+ * This is intended for pointers within shared memory regions which
+ * might be mapped at different addresses by different processes.
+ * For null pointers, a value of 1 is used. (0 is legitimate
+ * sometimes for nodes in circularly linked lists) This value was
+ * chosen as the least likely to generate an incorrect null, As
+ * there is no reason why any normal pointer would point 1 byte into
* its own pointer address.
*/
template<typename _Tp>
if (_M_diff == 1)
return 0;
else
- return reinterpret_cast<_Tp*>(
- const_cast<char*>(reinterpret_cast<const char*>(this))
- + _M_diff);
+ return reinterpret_cast<_Tp*>(reinterpret_cast<uintptr_t>(this)
+ + _M_diff);
}
void
if (!__arg)
_M_diff = 1;
else
- _M_diff = reinterpret_cast<char*>(__arg)
- - reinterpret_cast<char*>(this);
+ _M_diff = reinterpret_cast<uintptr_t>(__arg)
+ - reinterpret_cast<uintptr_t>(this);
}
// Comparison of pointers
inline bool
operator<(const _Relative_pointer_impl& __rarg) const
- { return (this->get() < __rarg.get()); }
+ { return (reinterpret_cast<uintptr_t>(this->get())
+ < reinterpret_cast<uintptr_t>(__rarg.get())); }
inline bool
operator==(const _Relative_pointer_impl& __rarg) const
- { return (this->get() == __rarg.get()); }
+ { return (reinterpret_cast<uintptr_t>(this->get())
+ == reinterpret_cast<uintptr_t>(__rarg.get())); }
private:
- std::ptrdiff_t _M_diff;
+ typedef __UINTPTR_TYPE__ uintptr_t;
+ uintptr_t _M_diff;
};
/**
if (_M_diff == 1)
return 0;
else
- return reinterpret_cast<const _Tp*>(
- (reinterpret_cast<const char*>(this)) + _M_diff);
+ return reinterpret_cast<const _Tp*>
+ (reinterpret_cast<uintptr_t>(this) + _M_diff);
}
void
if (!__arg)
_M_diff = 1;
else
- _M_diff = reinterpret_cast<const char*>(__arg)
- - reinterpret_cast<const char*>(this);
+ _M_diff = reinterpret_cast<uintptr_t>(__arg)
+ - reinterpret_cast<uintptr_t>(this);
}
// Comparison of pointers
inline bool
operator<(const _Relative_pointer_impl& __rarg) const
- { return (this->get() < __rarg.get()); }
+ { return (reinterpret_cast<uintptr_t>(this->get())
+ < reinterpret_cast<uintptr_t>(__rarg.get())); }
inline bool
operator==(const _Relative_pointer_impl& __rarg) const
- { return (this->get() == __rarg.get()); }
+ { return (reinterpret_cast<uintptr_t>(this->get())
+ == reinterpret_cast<uintptr_t>(__rarg.get())); }
private:
- std::ptrdiff_t _M_diff;
+ typedef __UINTPTR_TYPE__ uintptr_t;
+ uintptr_t _M_diff;
};
/**
* The specialization on this type helps resolve the problem of
- * reference to void, and eliminates the need to specialize _Pointer_adapter
- * for cases of void*, const void*, and so on.
+ * reference to void, and eliminates the need to specialize
+ * _Pointer_adapter for cases of void*, const void*, and so on.
*/
struct _Invalid_type { };
{ typedef const volatile _Invalid_type& reference; };
/**
- * This structure accomodates the way in which std::iterator_traits<>
- * is normally specialized for const T*, so that value_type is still T.
+ * This structure accommodates the way in which
+ * std::iterator_traits<> is normally specialized for const T*, so
+ * that value_type is still T.
*/
template<typename _Tp>
struct _Unqualified_type
struct _Unqualified_type<const _Tp>
{ typedef _Tp type; };
- template<typename _Tp>
- struct _Unqualified_type<volatile _Tp>
- { typedef volatile _Tp type; };
-
- template<typename _Tp>
- struct _Unqualified_type<volatile const _Tp>
- { typedef volatile _Tp type; };
-
/**
- * The following provides an 'alternative pointer' that works with the
- * containers when specified as the pointer typedef of the allocator.
+ * The following provides an 'alternative pointer' that works with
+ * the containers when specified as the pointer typedef of the
+ * allocator.
*
- * The pointer type used with the containers doesn't have to be this class,
- * but it must support the implicit conversions, pointer arithmetic,
- * comparison operators, etc. that are supported by this class, and avoid
- * raising compile-time ambiguities. Because creating a working pointer can
- * be challenging, this pointer template was designed to wrapper an
- * easier storage policy type, so that it becomes reusable for creating
- * other pointer types.
+ * The pointer type used with the containers doesn't have to be this
+ * class, but it must support the implicit conversions, pointer
+ * arithmetic, comparison operators, etc. that are supported by this
+ * class, and avoid raising compile-time ambiguities. Because
+ * creating a working pointer can be challenging, this pointer
+ * template was designed to wrapper an easier storage policy type,
+ * so that it becomes reusable for creating other pointer types.
*
- * A key point of this class is also that it allows container writers to
- * 'assume' Alocator::pointer is a typedef for a normal pointer. This class
- * supports most of the conventions of a true pointer, and can, for instance
- * handle implicit conversion to const and base class pointer types. The
- * only impositions on container writers to support extended pointers are:
- * 1) use the Allocator::pointer typedef appropriately for pointer types.
- * 2) if you need pointer casting, use the __pointer_cast<> functions
- * from ext/cast.h. This allows pointer cast operations to be overloaded
- * is necessary by custom pointers.
+ * A key point of this class is also that it allows container
+ * writers to 'assume' Allocator::pointer is a typedef for a normal
+ * pointer. This class supports most of the conventions of a true
+ * pointer, and can, for instance handle implicit conversion to
+ * const and base class pointer types. The only impositions on
+ * container writers to support extended pointers are: 1) use the
+ * Allocator::pointer typedef appropriately for pointer types. 2)
+ * if you need pointer casting, use the __pointer_cast<> functions
+ * from ext/cast.h. This allows pointer cast operations to be
+ * overloaded as necessary by custom pointers.
*
- * Note: The const qualifier works with this pointer adapter as follows:
+ * Note: The const qualifier works with this pointer adapter as
+ * follows:
*
* _Tp* == _Pointer_adapter<_Std_pointer_impl<_Tp> >;
* const _Tp* == _Pointer_adapter<_Std_pointer_impl<const _Tp> >;
{ return _Storage_policy::get()[__index]; }
// To allow implicit conversion to "bool", for "if (ptr)..."
+#if __cplusplus >= 201103L
+ explicit operator bool() const { return _Storage_policy::get() != 0; }
+#else
private:
typedef element_type*(_Pointer_adapter::*__unspecified_bool_type)() const;
inline bool
operator!() const
{ return (_Storage_policy::get() == 0); }
+#endif
// Pointer differences
inline friend std::ptrdiff_t
} \
// END of _CXX_POINTER_ARITH_OPERATOR_SET macro
- // Expand into the various pointer arithmatic operators needed.
+ // Expand into the various pointer arithmetic operators needed.
_CXX_POINTER_ARITH_OPERATOR_SET(short);
_CXX_POINTER_ARITH_OPERATOR_SET(unsigned short);
_CXX_POINTER_ARITH_OPERATOR_SET(int);
_CXX_POINTER_ARITH_OPERATOR_SET(unsigned int);
_CXX_POINTER_ARITH_OPERATOR_SET(long);
_CXX_POINTER_ARITH_OPERATOR_SET(unsigned long);
+#ifdef _GLIBCXX_USE_LONG_LONG
+ _CXX_POINTER_ARITH_OPERATOR_SET(long long);
+ _CXX_POINTER_ARITH_OPERATOR_SET(unsigned long long);
+#endif
// Mathematical Manipulators
inline _Pointer_adapter&
}
inline _Pointer_adapter
- operator++(int __unused)
+ operator++(int)
{
- _Pointer_adapter tmp(*this);
+ _Pointer_adapter __tmp(*this);
_Storage_policy::set(_Storage_policy::get() + 1);
- return tmp;
+ return __tmp;
}
inline _Pointer_adapter&
inline _Pointer_adapter
operator--(int)
{
- _Pointer_adapter tmp(*this);
+ _Pointer_adapter __tmp(*this);
_Storage_policy::set(_Storage_policy::get() - 1);
- return tmp;
+ return __tmp;
}
-
+
+#if __cpp_lib_three_way_comparison
+ friend std::strong_ordering
+ operator<=>(const _Pointer_adapter& __lhs, const _Pointer_adapter& __rhs)
+ noexcept
+ { return __lhs.get() <=> __rhs.get(); }
+#endif
}; // class _Pointer_adapter
-#define _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(OPERATOR,BLANK) \
+#define _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(OPERATOR) \
template<typename _Tp1, typename _Tp2> \
inline bool \
- operator OPERATOR##BLANK (const _Pointer_adapter<_Tp1>& __lhs, _Tp2 __rhs) \
- { return __lhs.get() OPERATOR##BLANK __rhs; } \
+ operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, _Tp2 __rhs) \
+ { return __lhs.get() OPERATOR __rhs; } \
\
template<typename _Tp1, typename _Tp2> \
inline bool \
- operator OPERATOR##BLANK (_Tp1 __lhs, const _Pointer_adapter<_Tp2>& __rhs) \
- { return __lhs OPERATOR##BLANK __rhs.get(); } \
+ operator OPERATOR(_Tp1 __lhs, const _Pointer_adapter<_Tp2>& __rhs) \
+ { return __lhs OPERATOR __rhs.get(); } \
\
template<typename _Tp1, typename _Tp2> \
inline bool \
- operator OPERATOR##BLANK (const _Pointer_adapter<_Tp1>& __lhs, \
+ operator OPERATOR(const _Pointer_adapter<_Tp1>& __lhs, \
const _Pointer_adapter<_Tp2>& __rhs) \
- { return __lhs.get() OPERATOR##BLANK __rhs.get(); } \
+ { return __lhs.get() OPERATOR __rhs.get(); } \
\
// End GCC_CXX_POINTER_COMPARISON_OPERATION_SET Macro
// Expand into the various comparison operators needed.
- _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(==,);
- _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(!=,);
- _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<,);
- _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<=,);
- _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>,);
- _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>=,);
+ _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(==)
+ _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(!=)
+ _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<)
+ _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(<=)
+ _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>)
+ _GCC_CXX_POINTER_COMPARISON_OPERATION_SET(>=)
// These are here for expressions like "ptr == 0", "ptr != 0"
template<typename _Tp>
{ return __rhs.get() != reinterpret_cast<void*>(__lhs); }
/**
- * Comparison operators for _Pointer_adapter defer to the base class'es
+ * Comparison operators for _Pointer_adapter defer to the base class'
* comparison operators, when possible.
*/
template<typename _Tp>
const _Pointer_adapter<_Tp>& __rhs)
{ return !(__lhs._Tp::operator<(__rhs)); }
+#if _GLIBCXX_HOSTED
template<typename _CharT, typename _Traits, typename _StoreT>
inline std::basic_ostream<_CharT, _Traits>&
operator<<(std::basic_ostream<_CharT, _Traits>& __os,
const _Pointer_adapter<_StoreT>& __p)
{ return (__os << __p.get()); }
+#endif // HOSTED
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
-_GLIBCXX_END_NAMESPACE
+#if __cplusplus >= 201103L
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<typename _Storage_policy>
+ struct pointer_traits<__gnu_cxx::_Pointer_adapter<_Storage_policy>>
+ {
+ /// The pointer type
+ typedef __gnu_cxx::_Pointer_adapter<_Storage_policy> pointer;
+ /// The type pointed to
+ typedef typename pointer::element_type element_type;
+ /// Type used to represent the difference between two pointers
+ typedef typename pointer::difference_type difference_type;
+
+ template<typename _Up>
+ using rebind = typename __gnu_cxx::_Pointer_adapter<
+ typename pointer_traits<_Storage_policy>::template rebind<_Up>>;
+
+ static pointer pointer_to(typename pointer::reference __r) noexcept
+ { return pointer(std::addressof(__r)); }
+ };
+
+#if __cpp_lib_concepts
+ template<typename _Policy>
+ struct indirectly_readable_traits<__gnu_cxx::_Pointer_adapter<_Policy>>
+ {
+ using value_type
+ = typename __gnu_cxx::_Pointer_adapter<_Policy>::value_type;
+ };
+#endif
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+#endif
#endif // _POINTER_H