1*38fd1498Szrj // Pointer Traits -*- C++ -*-
2*38fd1498Szrj
3*38fd1498Szrj // Copyright (C) 2011-2018 Free Software Foundation, Inc.
4*38fd1498Szrj //
5*38fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free
6*38fd1498Szrj // software; you can redistribute it and/or modify it under the
7*38fd1498Szrj // terms of the GNU General Public License as published by the
8*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj // any later version.
10*38fd1498Szrj
11*38fd1498Szrj // This library is distributed in the hope that it will be useful,
12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*38fd1498Szrj // GNU General Public License for more details.
15*38fd1498Szrj
16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj // 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj
20*38fd1498Szrj // You should have received a copy of the GNU General Public License and
21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23*38fd1498Szrj // <http://www.gnu.org/licenses/>.
24*38fd1498Szrj
25*38fd1498Szrj /** @file bits/ptr_traits.h
26*38fd1498Szrj * This is an internal header file, included by other library headers.
27*38fd1498Szrj * Do not attempt to use it directly. @headername{memory}
28*38fd1498Szrj */
29*38fd1498Szrj
30*38fd1498Szrj #ifndef _PTR_TRAITS_H
31*38fd1498Szrj #define _PTR_TRAITS_H 1
32*38fd1498Szrj
33*38fd1498Szrj #if __cplusplus >= 201103L
34*38fd1498Szrj
35*38fd1498Szrj #include <bits/move.h>
36*38fd1498Szrj
_GLIBCXX_VISIBILITY(default)37*38fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
38*38fd1498Szrj {
39*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
40*38fd1498Szrj
41*38fd1498Szrj class __undefined;
42*38fd1498Szrj
43*38fd1498Szrj // Given Template<T, ...> return T, otherwise invalid.
44*38fd1498Szrj template<typename _Tp>
45*38fd1498Szrj struct __get_first_arg
46*38fd1498Szrj { using type = __undefined; };
47*38fd1498Szrj
48*38fd1498Szrj template<template<typename, typename...> class _Template, typename _Tp,
49*38fd1498Szrj typename... _Types>
50*38fd1498Szrj struct __get_first_arg<_Template<_Tp, _Types...>>
51*38fd1498Szrj { using type = _Tp; };
52*38fd1498Szrj
53*38fd1498Szrj template<typename _Tp>
54*38fd1498Szrj using __get_first_arg_t = typename __get_first_arg<_Tp>::type;
55*38fd1498Szrj
56*38fd1498Szrj // Given Template<T, ...> and U return Template<U, ...>, otherwise invalid.
57*38fd1498Szrj template<typename _Tp, typename _Up>
58*38fd1498Szrj struct __replace_first_arg
59*38fd1498Szrj { };
60*38fd1498Szrj
61*38fd1498Szrj template<template<typename, typename...> class _Template, typename _Up,
62*38fd1498Szrj typename _Tp, typename... _Types>
63*38fd1498Szrj struct __replace_first_arg<_Template<_Tp, _Types...>, _Up>
64*38fd1498Szrj { using type = _Template<_Up, _Types...>; };
65*38fd1498Szrj
66*38fd1498Szrj template<typename _Tp, typename _Up>
67*38fd1498Szrj using __replace_first_arg_t = typename __replace_first_arg<_Tp, _Up>::type;
68*38fd1498Szrj
69*38fd1498Szrj template<typename _Tp>
70*38fd1498Szrj using __make_not_void
71*38fd1498Szrj = typename conditional<is_void<_Tp>::value, __undefined, _Tp>::type;
72*38fd1498Szrj
73*38fd1498Szrj /**
74*38fd1498Szrj * @brief Uniform interface to all pointer-like types
75*38fd1498Szrj * @ingroup pointer_abstractions
76*38fd1498Szrj */
77*38fd1498Szrj template<typename _Ptr>
78*38fd1498Szrj struct pointer_traits
79*38fd1498Szrj {
80*38fd1498Szrj private:
81*38fd1498Szrj template<typename _Tp>
82*38fd1498Szrj using __element_type = typename _Tp::element_type;
83*38fd1498Szrj
84*38fd1498Szrj template<typename _Tp>
85*38fd1498Szrj using __difference_type = typename _Tp::difference_type;
86*38fd1498Szrj
87*38fd1498Szrj template<typename _Tp, typename _Up, typename = void>
88*38fd1498Szrj struct __rebind : __replace_first_arg<_Tp, _Up> { };
89*38fd1498Szrj
90*38fd1498Szrj template<typename _Tp, typename _Up>
91*38fd1498Szrj struct __rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>>>
92*38fd1498Szrj { using type = typename _Tp::template rebind<_Up>; };
93*38fd1498Szrj
94*38fd1498Szrj public:
95*38fd1498Szrj /// The pointer type.
96*38fd1498Szrj using pointer = _Ptr;
97*38fd1498Szrj
98*38fd1498Szrj /// The type pointed to.
99*38fd1498Szrj using element_type
100*38fd1498Szrj = __detected_or_t<__get_first_arg_t<_Ptr>, __element_type, _Ptr>;
101*38fd1498Szrj
102*38fd1498Szrj /// The type used to represent the difference between two pointers.
103*38fd1498Szrj using difference_type
104*38fd1498Szrj = __detected_or_t<ptrdiff_t, __difference_type, _Ptr>;
105*38fd1498Szrj
106*38fd1498Szrj /// A pointer to a different type.
107*38fd1498Szrj template<typename _Up>
108*38fd1498Szrj using rebind = typename __rebind<_Ptr, _Up>::type;
109*38fd1498Szrj
110*38fd1498Szrj static _Ptr
111*38fd1498Szrj pointer_to(__make_not_void<element_type>& __e)
112*38fd1498Szrj { return _Ptr::pointer_to(__e); }
113*38fd1498Szrj
114*38fd1498Szrj static_assert(!is_same<element_type, __undefined>::value,
115*38fd1498Szrj "pointer type defines element_type or is like SomePointer<T, Args>");
116*38fd1498Szrj };
117*38fd1498Szrj
118*38fd1498Szrj /**
119*38fd1498Szrj * @brief Partial specialization for built-in pointers.
120*38fd1498Szrj * @ingroup pointer_abstractions
121*38fd1498Szrj */
122*38fd1498Szrj template<typename _Tp>
123*38fd1498Szrj struct pointer_traits<_Tp*>
124*38fd1498Szrj {
125*38fd1498Szrj /// The pointer type
126*38fd1498Szrj typedef _Tp* pointer;
127*38fd1498Szrj /// The type pointed to
128*38fd1498Szrj typedef _Tp element_type;
129*38fd1498Szrj /// Type used to represent the difference between two pointers
130*38fd1498Szrj typedef ptrdiff_t difference_type;
131*38fd1498Szrj
132*38fd1498Szrj template<typename _Up>
133*38fd1498Szrj using rebind = _Up*;
134*38fd1498Szrj
135*38fd1498Szrj /**
136*38fd1498Szrj * @brief Obtain a pointer to an object
137*38fd1498Szrj * @param __r A reference to an object of type @c element_type
138*38fd1498Szrj * @return @c addressof(__r)
139*38fd1498Szrj */
140*38fd1498Szrj static pointer
141*38fd1498Szrj pointer_to(__make_not_void<element_type>& __r) noexcept
142*38fd1498Szrj { return std::addressof(__r); }
143*38fd1498Szrj };
144*38fd1498Szrj
145*38fd1498Szrj /// Convenience alias for rebinding pointers.
146*38fd1498Szrj template<typename _Ptr, typename _Tp>
147*38fd1498Szrj using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>;
148*38fd1498Szrj
149*38fd1498Szrj template<typename _Tp>
150*38fd1498Szrj constexpr _Tp*
151*38fd1498Szrj __to_address(_Tp* __ptr) noexcept
152*38fd1498Szrj {
153*38fd1498Szrj static_assert(!std::is_function<_Tp>::value, "not a function pointer");
154*38fd1498Szrj return __ptr;
155*38fd1498Szrj }
156*38fd1498Szrj
157*38fd1498Szrj #if __cplusplus <= 201703L
158*38fd1498Szrj template<typename _Ptr>
159*38fd1498Szrj constexpr typename std::pointer_traits<_Ptr>::element_type*
160*38fd1498Szrj __to_address(const _Ptr& __ptr)
161*38fd1498Szrj { return std::__to_address(__ptr.operator->()); }
162*38fd1498Szrj #else
163*38fd1498Szrj template<typename _Ptr>
164*38fd1498Szrj constexpr auto
165*38fd1498Szrj __to_address(const _Ptr& __ptr) noexcept
166*38fd1498Szrj -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr))
167*38fd1498Szrj { return std::pointer_traits<_Ptr>::to_address(__ptr); }
168*38fd1498Szrj
169*38fd1498Szrj template<typename _Ptr, typename... _None>
170*38fd1498Szrj constexpr auto
171*38fd1498Szrj __to_address(const _Ptr& __ptr, _None...) noexcept
172*38fd1498Szrj { return std::__to_address(__ptr.operator->()); }
173*38fd1498Szrj
174*38fd1498Szrj /**
175*38fd1498Szrj * @brief Obtain address referenced by a pointer to an object
176*38fd1498Szrj * @param __ptr A pointer to an object
177*38fd1498Szrj * @return @c __ptr
178*38fd1498Szrj * @ingroup pointer_abstractions
179*38fd1498Szrj */
180*38fd1498Szrj template<typename _Tp>
181*38fd1498Szrj constexpr _Tp*
182*38fd1498Szrj to_address(_Tp* __ptr) noexcept
183*38fd1498Szrj { return std::__to_address(__ptr); }
184*38fd1498Szrj
185*38fd1498Szrj /**
186*38fd1498Szrj * @brief Obtain address referenced by a pointer to an object
187*38fd1498Szrj * @param __ptr A pointer to an object
188*38fd1498Szrj * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is
189*38fd1498Szrj well-formed, otherwise @c to_address(__ptr.operator->())
190*38fd1498Szrj * @ingroup pointer_abstractions
191*38fd1498Szrj */
192*38fd1498Szrj template<typename _Ptr>
193*38fd1498Szrj constexpr auto
194*38fd1498Szrj to_address(const _Ptr& __ptr) noexcept
195*38fd1498Szrj { return std::__to_address(__ptr); }
196*38fd1498Szrj #endif // C++2a
197*38fd1498Szrj
198*38fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
199*38fd1498Szrj } // namespace std
200*38fd1498Szrj
201*38fd1498Szrj #endif
202*38fd1498Szrj
203*38fd1498Szrj #endif
204