1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2006-2014. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/move for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10
11 #ifndef BOOST_MOVE_MAKE_UNIQUE_HPP_INCLUDED
12 #define BOOST_MOVE_MAKE_UNIQUE_HPP_INCLUDED
13
14 #ifndef BOOST_CONFIG_HPP
15 # include <boost/config.hpp>
16 #endif
17 #
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 # pragma once
20 #endif
21
22 #include <boost/move/detail/config_begin.hpp>
23 #include <boost/move/detail/workaround.hpp>
24 #include <boost/move/utility_core.hpp>
25 #include <boost/move/unique_ptr.hpp>
26 #include <cstddef> //for std::size_t
27 #include <boost/move/detail/unique_ptr_meta_utils.hpp>
28 #ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES
29 # include <boost/move/detail/fwd_macros.hpp>
30 #endif
31
32 //!\file
33 //! Defines "make_unique" functions, which are factories to create instances
34 //! of unique_ptr depending on the passed arguments.
35 //!
36 //! This header can be a bit heavyweight in C++03 compilers due to the use of the
37 //! preprocessor library, that's why it's a a separate header from <tt>unique_ptr.hpp</tt>
38
39 #if !defined(BOOST_MOVE_DOXYGEN_INVOKED)
40
41 namespace std { //no namespace versioning in clang+libc++
42
43 struct nothrow_t;
44
45 } //namespace std {
46
47 namespace boost{
48 namespace move_upmu {
49
50 //Compile time switch between
51 //single element, unknown bound array
52 //and known bound array
53 template<class T>
54 struct unique_ptr_if
55 {
56 typedef ::boost::movelib::unique_ptr<T> t_is_not_array;
57 };
58
59 template<class T>
60 struct unique_ptr_if<T[]>
61 {
62 typedef ::boost::movelib::unique_ptr<T[]> t_is_array_of_unknown_bound;
63 };
64
65 template<class T, std::size_t N>
66 struct unique_ptr_if<T[N]>
67 {
68 typedef void t_is_array_of_known_bound;
69 };
70
71 template <int Dummy = 0>
72 struct nothrow_holder
73 {
74 static std::nothrow_t *pnothrow;
75 };
76
77 template <int Dummy>
78 std::nothrow_t *nothrow_holder<Dummy>::pnothrow =
79 reinterpret_cast<std::nothrow_t *>(0x1234); //Avoid reference to null errors in sanitizers
80
81 } //namespace move_upmu {
82 } //namespace boost{
83
84 #endif //!defined(BOOST_MOVE_DOXYGEN_INVOKED)
85
86 namespace boost{
87 namespace movelib {
88
89 #if defined(BOOST_MOVE_DOXYGEN_INVOKED) || !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
90
91 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array.
92 //!
93 //! <b>Returns</b>: <tt>unique_ptr<T>(new T(std::forward<Args>(args)...))</tt>.
94 template<class T, class... Args>
BOOST_MOVE_DOC1ST(unique_ptr<T>,typename::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)95 inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
96 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)
97 make_unique(BOOST_FWD_REF(Args)... args)
98 { return unique_ptr<T>(new T(::boost::forward<Args>(args)...)); }
99
100 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array.
101 //!
102 //! <b>Returns</b>: <tt>unique_ptr<T>(new T(std::nothrow)(std::forward<Args>(args)...))</tt>.
103 template<class T, class... Args>
BOOST_MOVE_DOC1ST(unique_ptr<T>,typename::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)104 inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
105 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)
106 make_unique_nothrow(BOOST_FWD_REF(Args)... args)
107 { return unique_ptr<T>(new (*boost::move_upmu::nothrow_holder<>::pnothrow)T(::boost::forward<Args>(args)...)); }
108
109 #else
110 #define BOOST_MOVE_MAKE_UNIQUE_CODE(N)\
111 template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
112 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array\
113 make_unique( BOOST_MOVE_UREF##N)\
114 { return unique_ptr<T>( new T( BOOST_MOVE_FWD##N ) ); }\
115 \
116 template<class T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
117 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array\
118 make_unique_nothrow( BOOST_MOVE_UREF##N)\
119 { return unique_ptr<T>( new (*boost::move_upmu::nothrow_holder<>::pnothrow)T ( BOOST_MOVE_FWD##N ) ); }\
120 //
121 BOOST_MOVE_ITERATE_0TO9(BOOST_MOVE_MAKE_UNIQUE_CODE)
122 #undef BOOST_MOVE_MAKE_UNIQUE_CODE
123
124 #endif
125
126 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array.
127 //!
128 //! <b>Returns</b>: <tt>unique_ptr<T>(new T)</tt> (default initialization)
129 template<class T>
BOOST_MOVE_DOC1ST(unique_ptr<T>,typename::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)130 inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
131 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)
132 make_unique_definit()
133 {
134 return unique_ptr<T>(new T);
135 }
136
137 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is not an array.
138 //!
139 //! <b>Returns</b>: <tt>unique_ptr<T>(new T(std::nothrow)</tt> (default initialization)
140 template<class T>
BOOST_MOVE_DOC1ST(unique_ptr<T>,typename::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)141 inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
142 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_not_array)
143 make_unique_nothrow_definit()
144 {
145 return unique_ptr<T>(new (*boost::move_upmu::nothrow_holder<>::pnothrow)T);
146 }
147
148 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of
149 //! unknown bound.
150 //!
151 //! <b>Returns</b>: <tt>unique_ptr<T>(new remove_extent_t<T>[n]())</tt> (value initialization)
152 template<class T>
BOOST_MOVE_DOC1ST(unique_ptr<T>,typename::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)153 inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
154 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)
155 make_unique(std::size_t n)
156 {
157 typedef typename ::boost::move_upmu::remove_extent<T>::type U;
158 return unique_ptr<T>(new U[n]());
159 }
160
161 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of
162 //! unknown bound.
163 //!
164 //! <b>Returns</b>: <tt>unique_ptr<T>(new (std::nothrow)remove_extent_t<T>[n]())</tt> (value initialization)
165 template<class T>
BOOST_MOVE_DOC1ST(unique_ptr<T>,typename::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)166 inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
167 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)
168 make_unique_nothrow(std::size_t n)
169 {
170 typedef typename ::boost::move_upmu::remove_extent<T>::type U;
171 return unique_ptr<T>(new (*boost::move_upmu::nothrow_holder<>::pnothrow)U[n]());
172 }
173
174 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of
175 //! unknown bound.
176 //!
177 //! <b>Returns</b>: <tt>unique_ptr<T>(new remove_extent_t<T>[n])</tt> (default initialization)
178 template<class T>
BOOST_MOVE_DOC1ST(unique_ptr<T>,typename::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)179 inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
180 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)
181 make_unique_definit(std::size_t n)
182 {
183 typedef typename ::boost::move_upmu::remove_extent<T>::type U;
184 return unique_ptr<T>(new U[n]);
185 }
186
187 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is an array of
188 //! unknown bound.
189 //!
190 //! <b>Returns</b>: <tt>unique_ptr<T>(new (std::nothrow)remove_extent_t<T>[n])</tt> (default initialization)
191 template<class T>
BOOST_MOVE_DOC1ST(unique_ptr<T>,typename::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)192 inline BOOST_MOVE_DOC1ST(unique_ptr<T>,
193 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_unknown_bound)
194 make_unique_nothrow_definit(std::size_t n)
195 {
196 typedef typename ::boost::move_upmu::remove_extent<T>::type U;
197 return unique_ptr<T>(new (*boost::move_upmu::nothrow_holder<>::pnothrow) U[n]);
198 }
199
200 #if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
201
202 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is
203 //! an array of known bound.
204 template<class T, class... Args>
205 inline BOOST_MOVE_DOC1ST(unspecified,
206 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound)
207 make_unique(BOOST_FWD_REF(Args) ...) = delete;
208
209 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is
210 //! an array of known bound.
211 template<class T, class... Args>
212 inline BOOST_MOVE_DOC1ST(unspecified,
213 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound)
214 make_unique_definit(BOOST_FWD_REF(Args) ...) = delete;
215
216 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is
217 //! an array of known bound.
218 template<class T, class... Args>
219 inline BOOST_MOVE_DOC1ST(unspecified,
220 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound)
221 make_unique_nothrow(BOOST_FWD_REF(Args) ...) = delete;
222
223 //! <b>Remarks</b>: This function shall not participate in overload resolution unless T is
224 //! an array of known bound.
225 template<class T, class... Args>
226 inline BOOST_MOVE_DOC1ST(unspecified,
227 typename ::boost::move_upmu::unique_ptr_if<T>::t_is_array_of_known_bound)
228 make_unique_nothrow_definit(BOOST_FWD_REF(Args) ...) = delete;
229
230 #endif
231
232 } //namespace movelib {
233
234 } //namespace boost{
235
236 #include <boost/move/detail/config_end.hpp>
237
238 #endif //#ifndef BOOST_MOVE_MAKE_UNIQUE_HPP_INCLUDED
239