1    	// Pointer Traits -*- C++ -*-
2    	
3    	// Copyright (C) 2011-2013 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 <type_traits> // For _GLIBCXX_HAS_NESTED_TYPE
36   	
37   	namespace std _GLIBCXX_VISIBILITY(default)
38   	{
39   	_GLIBCXX_BEGIN_NAMESPACE_VERSION
40   	
41   	_GLIBCXX_HAS_NESTED_TYPE(element_type)
42   	_GLIBCXX_HAS_NESTED_TYPE(difference_type)
43   	
44   	  template<typename _Tp, bool = __has_element_type<_Tp>::value>
45   	    struct __ptrtr_elt_type;
46   	
47   	  template<typename _Tp>
48   	    struct __ptrtr_elt_type<_Tp, true>
49   	    {
50   	      typedef typename _Tp::element_type __type;
51   	    };
52   	
53   	  template<template<typename, typename...> class _SomePtr, typename _Tp,
54   	            typename... _Args>
55   	    struct __ptrtr_elt_type<_SomePtr<_Tp, _Args...>, false>
56   	    {
57   	      typedef _Tp __type;
58   	    };
59   	
60   	  template<typename _Tp, bool = __has_difference_type<_Tp>::value>
61   	    struct __ptrtr_diff_type
62   	    {
63   	      typedef typename _Tp::difference_type __type;
64   	    };
65   	
66   	  template<typename _Tp>
67   	    struct __ptrtr_diff_type<_Tp, false>
68   	    {
69   	      typedef ptrdiff_t __type;
70   	    };
71   	
72   	  template<typename _Ptr, typename _Up>
73   	    class __ptrtr_rebind_helper
74   	    {
75   	      template<typename _Ptr2, typename _Up2>
76   		static constexpr bool
77   	       	_S_chk(typename _Ptr2::template rebind<_Up2>*)
78   	       	{ return true; }
79   	
80   	      template<typename, typename>
81   	        static constexpr bool
82   	       	_S_chk(...)
83   	       	{ return false; }
84   	
85   	    public:
86   	      static const bool __value = _S_chk<_Ptr, _Up>(nullptr);
87   	    };
88   	
89   	  template<typename _Ptr, typename _Up>
90   	    const bool __ptrtr_rebind_helper<_Ptr, _Up>::__value;
91   	
92   	  template<typename _Tp, typename _Up,
93   	           bool = __ptrtr_rebind_helper<_Tp, _Up>::__value>
94   	    struct __ptrtr_rebind;
95   	
96   	  template<typename _Tp, typename _Up>
97   	    struct __ptrtr_rebind<_Tp, _Up, true>
98   	    {
99   	      typedef typename _Tp::template rebind<_Up> __type;
100  	    };
101  	
102  	  template<template<typename, typename...> class _SomePtr, typename _Up,
103  	            typename _Tp, typename... _Args>
104  	    struct __ptrtr_rebind<_SomePtr<_Tp, _Args...>, _Up, false>
105  	    {
106  	      typedef _SomePtr<_Up, _Args...> __type;
107  	    };
108  	
109  	  template<typename _Tp, typename = typename remove_cv<_Tp>::type>
110  	    struct __ptrtr_not_void
111  	    {
112  	      typedef _Tp __type;
113  	    };
114  	
115  	  template<typename _Tp>
116  	    struct __ptrtr_not_void<_Tp, void>
117  	    {
118  	      struct __type { };
119  	    };
120  	
121  	  template<typename _Ptr>
122  	    class __ptrtr_pointer_to
123  	    {
124  	      typedef typename __ptrtr_elt_type<_Ptr>::__type   __orig_type;
125  	      typedef typename __ptrtr_not_void<__orig_type>::__type __element_type;
126  	
127  	    public:
128  	      static _Ptr pointer_to(__element_type& __e)
129  	      { return _Ptr::pointer_to(__e); }
130  	    };
131  	
132  	  /**
133  	   * @brief  Uniform interface to all pointer-like types
134  	   * @ingroup pointer_abstractions
135  	  */
136  	  template<typename _Ptr>
137  	    struct pointer_traits : __ptrtr_pointer_to<_Ptr>
138  	    {
139  	      /// The pointer type
140  	      typedef _Ptr                                      pointer;
141  	      /// The type pointed to
142  	      typedef typename __ptrtr_elt_type<_Ptr>::__type   element_type;
143  	      /// Type used to represent the difference between two pointers
144  	      typedef typename __ptrtr_diff_type<_Ptr>::__type  difference_type;
145  	
146  	      template<typename _Up>
147  	        using rebind = typename __ptrtr_rebind<_Ptr, _Up>::__type;
148  	    };
149  	
150  	  /**
151  	   * @brief  Partial specialization for built-in pointers.
152  	   * @ingroup pointer_abstractions
153  	  */
154  	  template<typename _Tp>
155  	    struct pointer_traits<_Tp*>
156  	    {
157  	      /// The pointer type
158  	      typedef _Tp* pointer;
159  	      /// The type pointed to
160  	      typedef _Tp  element_type;
161  	      /// Type used to represent the difference between two pointers
162  	      typedef ptrdiff_t difference_type;
163  	
164  	      template<typename _Up>
165  	        using rebind = _Up*;
166  	
167  	      /**
168  	       *  @brief  Obtain a pointer to an object
169  	       *  @param  __r  A reference to an object of type @c element_type
170  	       *  @return @c addressof(__r)
171  	      */
172  	      static pointer
173  	      pointer_to(typename __ptrtr_not_void<element_type>::__type& __r) noexcept
174  	      { return std::addressof(__r); }
175  	    };
176  	
177  	_GLIBCXX_END_NAMESPACE_VERSION
178  	} // namespace std
179  	
180  	#endif
181  	
182  	#endif
183