1// Pointer Traits -*- C++ -*- 2 3// Copyright (C) 2011-2020 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#define __cpp_lib_constexpr_memory 201811L 39namespace __gnu_debug { struct _Safe_iterator_base; } 40#endif 41 42namespace std _GLIBCXX_VISIBILITY(default) 43{ 44_GLIBCXX_BEGIN_NAMESPACE_VERSION 45 46 class __undefined; 47 48 // Given Template<T, ...> return T, otherwise invalid. 49 template<typename _Tp> 50 struct __get_first_arg 51 { using type = __undefined; }; 52 53 template<template<typename, typename...> class _Template, typename _Tp, 54 typename... _Types> 55 struct __get_first_arg<_Template<_Tp, _Types...>> 56 { using type = _Tp; }; 57 58 template<typename _Tp> 59 using __get_first_arg_t = typename __get_first_arg<_Tp>::type; 60 61 // Given Template<T, ...> and U return Template<U, ...>, otherwise invalid. 62 template<typename _Tp, typename _Up> 63 struct __replace_first_arg 64 { }; 65 66 template<template<typename, typename...> class _Template, typename _Up, 67 typename _Tp, typename... _Types> 68 struct __replace_first_arg<_Template<_Tp, _Types...>, _Up> 69 { using type = _Template<_Up, _Types...>; }; 70 71 template<typename _Tp, typename _Up> 72 using __replace_first_arg_t = typename __replace_first_arg<_Tp, _Up>::type; 73 74 template<typename _Tp> 75 using __make_not_void 76 = typename conditional<is_void<_Tp>::value, __undefined, _Tp>::type; 77 78 /** 79 * @brief Uniform interface to all pointer-like types 80 * @ingroup pointer_abstractions 81 */ 82 template<typename _Ptr> 83 struct pointer_traits 84 { 85 private: 86 template<typename _Tp> 87 using __element_type = typename _Tp::element_type; 88 89 template<typename _Tp> 90 using __difference_type = typename _Tp::difference_type; 91 92 template<typename _Tp, typename _Up, typename = void> 93 struct __rebind : __replace_first_arg<_Tp, _Up> { }; 94 95 template<typename _Tp, typename _Up> 96 struct __rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>>> 97 { using type = typename _Tp::template rebind<_Up>; }; 98 99 public: 100 /// The pointer type. 101 using pointer = _Ptr; 102 103 /// The type pointed to. 104 using element_type 105 = __detected_or_t<__get_first_arg_t<_Ptr>, __element_type, _Ptr>; 106 107 /// The type used to represent the difference between two pointers. 108 using difference_type 109 = __detected_or_t<ptrdiff_t, __difference_type, _Ptr>; 110 111 /// A pointer to a different type. 112 template<typename _Up> 113 using rebind = typename __rebind<_Ptr, _Up>::type; 114 115 static _Ptr 116 pointer_to(__make_not_void<element_type>& __e) 117 { return _Ptr::pointer_to(__e); } 118 119 static_assert(!is_same<element_type, __undefined>::value, 120 "pointer type defines element_type or is like SomePointer<T, Args>"); 121 }; 122 123 /** 124 * @brief Partial specialization for built-in pointers. 125 * @ingroup pointer_abstractions 126 */ 127 template<typename _Tp> 128 struct pointer_traits<_Tp*> 129 { 130 /// The pointer type 131 typedef _Tp* pointer; 132 /// The type pointed to 133 typedef _Tp element_type; 134 /// Type used to represent the difference between two pointers 135 typedef ptrdiff_t difference_type; 136 137 template<typename _Up> 138 using rebind = _Up*; 139 140 /** 141 * @brief Obtain a pointer to an object 142 * @param __r A reference to an object of type @c element_type 143 * @return @c addressof(__r) 144 */ 145 static _GLIBCXX20_CONSTEXPR pointer 146 pointer_to(__make_not_void<element_type>& __r) noexcept 147 { return std::addressof(__r); } 148 }; 149 150 /// Convenience alias for rebinding pointers. 151 template<typename _Ptr, typename _Tp> 152 using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>; 153 154 template<typename _Tp> 155 constexpr _Tp* 156 __to_address(_Tp* __ptr) noexcept 157 { 158 static_assert(!std::is_function<_Tp>::value, "not a function pointer"); 159 return __ptr; 160 } 161 162#if __cplusplus <= 201703L 163 template<typename _Ptr> 164 constexpr typename std::pointer_traits<_Ptr>::element_type* 165 __to_address(const _Ptr& __ptr) 166 { return std::__to_address(__ptr.operator->()); } 167#else 168 template<typename _Ptr> 169 constexpr auto 170 __to_address(const _Ptr& __ptr) noexcept 171 -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr)) 172 { return std::pointer_traits<_Ptr>::to_address(__ptr); } 173 174 template<typename _Ptr, typename... _None> 175 constexpr auto 176 __to_address(const _Ptr& __ptr, _None...) noexcept 177 { 178 if constexpr (is_base_of_v<__gnu_debug::_Safe_iterator_base, _Ptr>) 179 return std::__to_address(__ptr.base().operator->()); 180 else 181 return std::__to_address(__ptr.operator->()); 182 } 183 184#define __cpp_lib_to_address 201711L 185 186 /** 187 * @brief Obtain address referenced by a pointer to an object 188 * @param __ptr A pointer to an object 189 * @return @c __ptr 190 * @ingroup pointer_abstractions 191 */ 192 template<typename _Tp> 193 constexpr _Tp* 194 to_address(_Tp* __ptr) noexcept 195 { return std::__to_address(__ptr); } 196 197 /** 198 * @brief Obtain address referenced by a pointer to an object 199 * @param __ptr A pointer to an object 200 * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is 201 well-formed, otherwise @c to_address(__ptr.operator->()) 202 * @ingroup pointer_abstractions 203 */ 204 template<typename _Ptr> 205 constexpr auto 206 to_address(const _Ptr& __ptr) noexcept 207 { return std::__to_address(__ptr); } 208#endif // C++2a 209 210_GLIBCXX_END_NAMESPACE_VERSION 211} // namespace std 212 213#endif 214 215#endif 216