1    	// Uses-allocator Construction -*- C++ -*-
2    	
3    	// Copyright (C) 2010-2017 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   	#ifndef _USES_ALLOCATOR_H
26   	#define _USES_ALLOCATOR_H 1
27   	
28   	#if __cplusplus < 201103L
29   	# include <bits/c++0x_warning.h>
30   	#else
31   	
32   	#include <type_traits>
33   	#include <bits/move.h>
34   	
35   	namespace std _GLIBCXX_VISIBILITY(default)
36   	{
37   	_GLIBCXX_BEGIN_NAMESPACE_VERSION
38   	
39   	  struct __erased_type { };
40   	
41   	  template<typename _Alloc, typename _Tp>
42   	    using __is_erased_or_convertible
43   	      = __or_<is_same<_Tp, __erased_type>, is_convertible<_Alloc, _Tp>>;
44   	
45   	  /// [allocator.tag]
46   	  struct allocator_arg_t { explicit allocator_arg_t() = default; };
47   	
48   	  _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg =
49   	    allocator_arg_t();
50   	
51   	  template<typename _Tp, typename _Alloc, typename = __void_t<>>
52   	    struct __uses_allocator_helper
53   	    : false_type { };
54   	
55   	  template<typename _Tp, typename _Alloc>
56   	    struct __uses_allocator_helper<_Tp, _Alloc,
57   					   __void_t<typename _Tp::allocator_type>>
58   	    : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type
59   	    { };
60   	
61   	  /// [allocator.uses.trait]
62   	  template<typename _Tp, typename _Alloc>
63   	    struct uses_allocator
64   	    : __uses_allocator_helper<_Tp, _Alloc>::type
65   	    { };
66   	
67   	  struct __uses_alloc_base { };
68   	
69   	  struct __uses_alloc0 : __uses_alloc_base
70   	  {
71   	    struct _Sink { void operator=(const void*) { } } _M_a;
72   	  };
73   	
74   	  template<typename _Alloc>
75   	    struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; };
76   	
77   	  template<typename _Alloc>
78   	    struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; };
79   	
80   	  template<bool, typename _Tp, typename _Alloc, typename... _Args>
81   	    struct __uses_alloc;
82   	
83   	  template<typename _Tp, typename _Alloc, typename... _Args>
84   	    struct __uses_alloc<true, _Tp, _Alloc, _Args...>
85   	    : conditional<
86   	        is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value,
87   	        __uses_alloc1<_Alloc>,
88   	       	__uses_alloc2<_Alloc>>::type
89   	    {
90   	      static_assert(__or_<
91   		  is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>,
92   		  is_constructible<_Tp, _Args..., _Alloc>>::value, "construction with"
93   		  " an allocator must be possible if uses_allocator is true");
94   	    };
95   	
96   	  template<typename _Tp, typename _Alloc, typename... _Args>
97   	    struct __uses_alloc<false, _Tp, _Alloc, _Args...>
98   	    : __uses_alloc0 { };
99   	
100  	  template<typename _Tp, typename _Alloc, typename... _Args>
101  	    using __uses_alloc_t =
102  	      __uses_alloc<uses_allocator<_Tp, _Alloc>::value, _Tp, _Alloc, _Args...>;
103  	
104  	  template<typename _Tp, typename _Alloc, typename... _Args>
105  	    inline __uses_alloc_t<_Tp, _Alloc, _Args...>
106  	    __use_alloc(const _Alloc& __a)
107  	    {
108  	      __uses_alloc_t<_Tp, _Alloc, _Args...> __ret;
109  	      __ret._M_a = std::__addressof(__a);
110  	      return __ret;
111  	    }
112  	
113  	  template<typename _Tp, typename _Alloc, typename... _Args>
114  	    void
115  	    __use_alloc(const _Alloc&&) = delete;
116  	
117  	#if __cplusplus > 201402L
118  	  template <typename _Tp, typename _Alloc>
119  	    inline constexpr bool uses_allocator_v =
120  	      uses_allocator<_Tp, _Alloc>::value;
121  	#endif // C++17
122  	
123  	  template<template<typename...> class _Predicate,
124  		   typename _Tp, typename _Alloc, typename... _Args>
125  	    struct __is_uses_allocator_predicate
126  	    : conditional<uses_allocator<_Tp, _Alloc>::value,
127  	      __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>,
128  		    _Predicate<_Tp, _Args..., _Alloc>>,
129  	      _Predicate<_Tp, _Args...>>::type { };
130  	
131  	  template<typename _Tp, typename _Alloc, typename... _Args>
132  	    struct __is_uses_allocator_constructible
133  	    : __is_uses_allocator_predicate<is_constructible, _Tp, _Alloc, _Args...>
134  	    { };
135  	
136  	#if __cplusplus >= 201402L
137  	  template<typename _Tp, typename _Alloc, typename... _Args>
138  	    _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v =
139  	      __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
140  	#endif // C++14
141  	
142  	  template<typename _Tp, typename _Alloc, typename... _Args>
143  	    struct __is_nothrow_uses_allocator_constructible
144  	    : __is_uses_allocator_predicate<is_nothrow_constructible,
145  					    _Tp, _Alloc, _Args...>
146  	    { };
147  	
148  	
149  	#if __cplusplus >= 201402L
150  	  template<typename _Tp, typename _Alloc, typename... _Args>
151  	    _GLIBCXX17_INLINE constexpr bool
152  	    __is_nothrow_uses_allocator_constructible_v =
153  	      __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value;
154  	#endif // C++14
155  	
156  	  template<typename _Tp, typename... _Args>
157  	    void __uses_allocator_construct_impl(__uses_alloc0 __a, _Tp* __ptr,
158  						 _Args&&... __args)
159  	    { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); }
160  	
161  	  template<typename _Tp, typename _Alloc, typename... _Args>
162  	    void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr,
163  						 _Args&&... __args)
164  	    {
165  	      ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a,
166  				       std::forward<_Args>(__args)...);
167  	    }
168  	
169  	  template<typename _Tp, typename _Alloc, typename... _Args>
170  	    void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr,
171  						 _Args&&... __args)
172  	    { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); }
173  	
174  	  template<typename _Tp, typename _Alloc, typename... _Args>
175  	    void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr,
176  					    _Args&&... __args)
177  	    {
178  	      __uses_allocator_construct_impl(__use_alloc<_Tp, _Alloc, _Args...>(__a),
179  					      __ptr, std::forward<_Args>(__args)...);
180  	    }
181  	
182  	_GLIBCXX_END_NAMESPACE_VERSION
183  	} // namespace std
184  	
185  	#endif
186  	#endif
187