xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/bits/ptr_traits.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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