1// Pointer Traits -*- C++ -*-
2
3// Copyright (C) 2011-2022 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library.  This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/ptr_traits.h
26 *  This is an internal header file, included by other library headers.
27 *  Do not attempt to use it directly. @headername{memory}
28 */
29
30#ifndef _PTR_TRAITS_H
31#define _PTR_TRAITS_H 1
32
33#if __cplusplus >= 201103L
34
35#include <bits/move.h>
36
37#if __cplusplus > 201703L
38#include <concepts>
39# ifndef __cpp_lib_constexpr_memory
40// Defined to a newer value in bits/unique_ptr.h for C++23
41#  define __cpp_lib_constexpr_memory 201811L
42# endif
43namespace __gnu_debug { struct _Safe_iterator_base; }
44#endif
45
46namespace std _GLIBCXX_VISIBILITY(default)
47{
48_GLIBCXX_BEGIN_NAMESPACE_VERSION
49
50  class __undefined;
51
52  // For a specialization `SomeTemplate<T, Types...>` the member `type` is T,
53  // otherwise `type` is `__undefined`.
54  template<typename _Tp>
55    struct __get_first_arg
56    { using type = __undefined; };
57
58  template<template<typename, typename...> class _SomeTemplate, typename _Tp,
59           typename... _Types>
60    struct __get_first_arg<_SomeTemplate<_Tp, _Types...>>
61    { using type = _Tp; };
62
63  // For a specialization `SomeTemplate<T, Args...>` and a type `U` the member
64  // `type` is `SomeTemplate<U, Args...>`, otherwise there is no member `type`.
65  template<typename _Tp, typename _Up>
66    struct __replace_first_arg
67    { };
68
69  template<template<typename, typename...> class _SomeTemplate, typename _Up,
70           typename _Tp, typename... _Types>
71    struct __replace_first_arg<_SomeTemplate<_Tp, _Types...>, _Up>
72    { using type = _SomeTemplate<_Up, _Types...>; };
73
74#if __cpp_concepts
75  // When concepts are supported detection of _Ptr::element_type is done
76  // by a requires-clause, so __ptr_traits_elem_t only needs to do this:
77  template<typename _Ptr>
78    using __ptr_traits_elem_t = typename __get_first_arg<_Ptr>::type;
79#else
80  // Detect the element type of a pointer-like type.
81  template<typename _Ptr, typename = void>
82    struct __ptr_traits_elem : __get_first_arg<_Ptr>
83    { };
84
85  // Use _Ptr::element_type if is a valid type.
86  template<typename _Ptr>
87    struct __ptr_traits_elem<_Ptr, __void_t<typename _Ptr::element_type>>
88    { using type = typename _Ptr::element_type; };
89
90  template<typename _Ptr>
91    using __ptr_traits_elem_t = typename __ptr_traits_elem<_Ptr>::type;
92#endif
93
94  // Define pointer_traits<P>::pointer_to.
95  template<typename _Ptr, typename _Elt, bool = is_void<_Elt>::value>
96    struct __ptr_traits_ptr_to
97    {
98      using pointer = _Ptr;
99      using element_type = _Elt;
100
101      /**
102       *  @brief  Obtain a pointer to an object
103       *  @param  __r  A reference to an object of type `element_type`
104       *  @return `pointer::pointer_to(__e)`
105       *  @pre `pointer::pointer_to(__e)` is a valid expression.
106      */
107      static pointer
108      pointer_to(element_type& __e)
109#if __cpp_lib_concepts
110      requires requires {
111	{ pointer::pointer_to(__e) } -> convertible_to<pointer>;
112      }
113#endif
114      { return pointer::pointer_to(__e); }
115    };
116
117  // Do not define pointer_traits<P>::pointer_to if element type is void.
118  template<typename _Ptr, typename _Elt>
119    struct __ptr_traits_ptr_to<_Ptr, _Elt, true>
120    { };
121
122  // Partial specialization defining pointer_traits<T*>::pointer_to(T&).
123  template<typename _Tp>
124    struct __ptr_traits_ptr_to<_Tp*, _Tp, false>
125    {
126      using pointer = _Tp*;
127      using element_type = _Tp;
128
129      /**
130       *  @brief  Obtain a pointer to an object
131       *  @param  __r  A reference to an object of type `element_type`
132       *  @return `addressof(__r)`
133      */
134      static _GLIBCXX20_CONSTEXPR pointer
135      pointer_to(element_type& __r) noexcept
136      { return std::addressof(__r); }
137    };
138
139  template<typename _Ptr, typename _Elt>
140    struct __ptr_traits_impl : __ptr_traits_ptr_to<_Ptr, _Elt>
141    {
142    private:
143      template<typename _Tp, typename = void>
144	struct __difference { using type = ptrdiff_t; };
145
146      template<typename _Tp>
147#if __cpp_concepts
148	requires requires { typename _Tp::difference_type; }
149	struct __difference<_Tp>
150#else
151	struct __difference<_Tp, __void_t<typename _Tp::difference_type>>
152#endif
153	{ using type = typename _Tp::difference_type; };
154
155      template<typename _Tp, typename _Up, typename = void>
156	struct __rebind : __replace_first_arg<_Tp, _Up> { };
157
158      template<typename _Tp, typename _Up>
159#if __cpp_concepts
160	requires requires { typename _Tp::template rebind<_Up>; }
161	struct __rebind<_Tp, _Up>
162#else
163	struct __rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>>>
164#endif
165	{ using type = typename _Tp::template rebind<_Up>; };
166
167    public:
168      /// The pointer type.
169      using pointer = _Ptr;
170
171      /// The type pointed to.
172      using element_type = _Elt;
173
174      /// The type used to represent the difference between two pointers.
175      using difference_type = typename __difference<_Ptr>::type;
176
177      /// A pointer to a different type.
178      template<typename _Up>
179        using rebind = typename __rebind<_Ptr, _Up>::type;
180    };
181
182  // _GLIBCXX_RESOLVE_LIB_DEFECTS
183  // 3545. std::pointer_traits should be SFINAE-friendly
184  template<typename _Ptr>
185    struct __ptr_traits_impl<_Ptr, __undefined>
186    { };
187
188  /**
189   * @brief  Uniform interface to all pointer-like types
190   * @ingroup pointer_abstractions
191   * @since C++11
192  */
193  template<typename _Ptr>
194    struct pointer_traits : __ptr_traits_impl<_Ptr, __ptr_traits_elem_t<_Ptr>>
195    { };
196
197#if __cpp_concepts
198  template<typename _Ptr> requires requires { typename _Ptr::element_type; }
199    struct pointer_traits<_Ptr>
200    : __ptr_traits_impl<_Ptr, typename _Ptr::element_type>
201    { };
202#endif
203
204  /**
205   * @brief  Partial specialization for built-in pointers.
206   * @ingroup pointer_abstractions
207   * @since C++11
208  */
209  template<typename _Tp>
210    struct pointer_traits<_Tp*> : __ptr_traits_ptr_to<_Tp*, _Tp>
211    {
212      /// The pointer type
213      typedef _Tp* pointer;
214      /// The type pointed to
215      typedef _Tp  element_type;
216      /// Type used to represent the difference between two pointers
217      typedef ptrdiff_t difference_type;
218      /// A pointer to a different type.
219      template<typename _Up> using rebind = _Up*;
220    };
221
222  /// Convenience alias for rebinding pointers.
223  template<typename _Ptr, typename _Tp>
224    using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>;
225
226  template<typename _Tp>
227    constexpr _Tp*
228    __to_address(_Tp* __ptr) noexcept
229    {
230      static_assert(!std::is_function<_Tp>::value, "not a function pointer");
231      return __ptr;
232    }
233
234#if __cplusplus <= 201703L
235  template<typename _Ptr>
236    constexpr typename std::pointer_traits<_Ptr>::element_type*
237    __to_address(const _Ptr& __ptr)
238    { return std::__to_address(__ptr.operator->()); }
239#else
240  template<typename _Ptr>
241    constexpr auto
242    __to_address(const _Ptr& __ptr) noexcept
243    -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr))
244    { return std::pointer_traits<_Ptr>::to_address(__ptr); }
245
246  template<typename _Ptr, typename... _None>
247    constexpr auto
248    __to_address(const _Ptr& __ptr, _None...) noexcept
249    {
250      if constexpr (is_base_of_v<__gnu_debug::_Safe_iterator_base, _Ptr>)
251	return std::__to_address(__ptr.base().operator->());
252      else
253	return std::__to_address(__ptr.operator->());
254    }
255
256#define __cpp_lib_to_address 201711L
257
258  /**
259   * @brief Obtain address referenced by a pointer to an object
260   * @param __ptr A pointer to an object
261   * @return @c __ptr
262   * @ingroup pointer_abstractions
263  */
264  template<typename _Tp>
265    constexpr _Tp*
266    to_address(_Tp* __ptr) noexcept
267    { return std::__to_address(__ptr); }
268
269  /**
270   * @brief Obtain address referenced by a pointer to an object
271   * @param __ptr A pointer to an object
272   * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is
273             well-formed, otherwise @c to_address(__ptr.operator->())
274   * @ingroup pointer_abstractions
275  */
276  template<typename _Ptr>
277    constexpr auto
278    to_address(const _Ptr& __ptr) noexcept
279    { return std::__to_address(__ptr); }
280#endif // C++2a
281
282_GLIBCXX_END_NAMESPACE_VERSION
283} // namespace std
284
285#endif
286
287#endif
288