MongoDB C++ Driver mongocxx-3.11.0
Loading...
Searching...
No Matches
make_unique.hpp
Go to the documentation of this file.
1// Copyright 2009-present MongoDB, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
17#include <memory>
18
20
21#pragma push_macro("BSONCXX_DETAIL_USE_STD_MAKE_UNIQUE")
22#undef BSONCXX_DETAIL_USE_STD_MAKE_UNIQUE
23
24#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
25 (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
26#define BSONCXX_DETAIL_USE_STD_MAKE_UNIQUE
27#endif
28
29// Only define bsoncxx implementation details when necessary.
30#if !defined(BSONCXX_DETAIL_USE_STD_MAKE_UNIQUE) || !defined(__cpp_lib_smart_ptr_for_overwrite)
31
32#include <cstddef>
33#include <type_traits>
34#include <utility>
35
37
38namespace bsoncxx {
39namespace v_noabi {
40namespace stdx {
41namespace detail {
42
43// Switch backend of make_unique by the type we are creating.
44// It would be easier to 'if constexpr' on whether we are an array and whether to direct-init or
45// value-init, but we don't have if-constexpr and we need it to guard against an uterance of a
46// possibly-illegal 'new' expression.
47template <typename T>
48struct make_unique_impl {
49 // For make_unique:
50 template <typename... Args,
51 // Guard on constructible-from:
52 typename = decltype(new T(std::declval<Args>()...))>
53 static std::unique_ptr<T> make(std::true_type /* direct-init */, Args&&... args) {
54 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
55 }
56
57 // For make_unique_for_overwrite:
58 template <typename U = T,
59 // Guard on whether T is value-initializable:
60 // (Hide behind a deduced 'U' to defer the evaluation of
61 // this default template argument until overload resolution)
62 typename = decltype(new U)>
63 static std::unique_ptr<T> make(std::false_type /* value-init */) {
64 return std::unique_ptr<T>(new T);
65 }
66};
67
68// For unbounded arrays:
69template <typename Elem>
70struct make_unique_impl<Elem[]> {
71 template <typename ShouldDirectInit,
72 // Guard on whether the new-expression will be legal:
73 typename = decltype(new Elem[std::declval<std::size_t>()])>
74 static std::unique_ptr<Elem[]> make(ShouldDirectInit, std::size_t count) {
75 // These can share a function via a plain if, because both new expressions
76 // must be semantically valid
77 if (ShouldDirectInit()) {
78 return std::unique_ptr<Elem[]>(new Elem[count]());
79 } else {
80 return std::unique_ptr<Elem[]>(new Elem[count]);
81 }
82 }
83};
84
85// Bounded arrays are disallowed:
86template <typename Elem, std::size_t N>
87struct make_unique_impl<Elem[N]> {};
88
89// References are nonsense:
90template <typename T>
91struct make_unique_impl<T&> {};
92
93// References are nonsense:
94template <typename T>
95struct make_unique_impl<T&&> {};
96
97} // namespace detail
98} // namespace stdx
99} // namespace v_noabi
100} // namespace bsoncxx
101
102#endif // !defined(BSONCXX_DETAIL_USE_STD_MAKE_UNIQUE) ||
103 // !defined(__cpp_lib_smart_ptr_for_overwrite)
104
105namespace bsoncxx {
106namespace v_noabi {
107namespace stdx {
108
109// Unlike other C++17 polyfill features, this is a C++14 feature.
110// Use feature testing rather than polyfill library selection macros.
111#if defined(BSONCXX_DETAIL_USE_STD_MAKE_UNIQUE)
112using ::std::make_unique;
113#else
114
115// Equivalent to `std::make_unique<T>(args...)` where `T` is a non-array type.
116// @cond DOXYGEN_DISABLE
117template <typename T,
118 typename... Args,
119 typename Impl = detail::make_unique_impl<T>,
120 typename std::enable_if<!std::is_array<T>::value,
121 decltype(Impl::make(std::true_type{}, std::declval<Args>()...),
122 void())>::type* = nullptr>
123std::unique_ptr<T> make_unique(Args&&... args) {
124 return Impl::make(std::true_type{}, std::forward<Args>(args)...);
125}
126// @endcond
127
128// Equivalent to `std::make_unique<T>(count)` where `T` is an array type.
129// @cond DOXYGEN_DISABLE
130template <
131 typename T,
132 typename Impl = detail::make_unique_impl<T>,
133 typename std::enable_if<std::is_array<T>::value,
134 decltype(Impl::make(std::true_type{}, std::declval<std::size_t>()),
135 void())>::type* = nullptr>
136std::unique_ptr<T> make_unique(std::size_t count) {
137 return Impl::make(std::true_type{}, count);
138}
139// @endcond DOXYGEN_DISABLE
140
141#endif
142
143// Unlike other C++17 polyfill features, this is a C++20 feature.
144// Use feature testing rather than polyfill library selection macros.
145#if defined(__cpp_lib_smart_ptr_for_overwrite)
146using ::std::make_unique_for_overwrite;
147#else
148
149// Equivalent to `std::make_unique_for_overwrite<T>()` where `T` is a non-array type.
150template <typename T,
151 typename Impl = detail::make_unique_impl<T>,
152 typename std::enable_if<!std::is_array<T>::value,
153 decltype(Impl::make(std::false_type{}), void())>::type* = nullptr>
154std::unique_ptr<T> make_unique_for_overwrite() {
155 return Impl::make(std::false_type{});
156}
157
158// Equivalent to `std::make_unique_for_overwrite<T>(count)` where `T` is an array type.
159template <
160 typename T,
161 typename Impl = detail::make_unique_impl<T>,
162 typename std::enable_if<std::is_array<T>::value,
163 decltype(Impl::make(std::false_type{}, std::declval<std::size_t>()),
164 void())>::type* = nullptr>
165std::unique_ptr<T> make_unique_for_overwrite(std::size_t count) {
166 return Impl::make(std::false_type{}, count);
167}
168
169#endif
170
171} // namespace stdx
172} // namespace v_noabi
173} // namespace bsoncxx
174
175#pragma pop_macro("BSONCXX_DETAIL_USE_STD_MAKE_UNIQUE")
176
178
179namespace bsoncxx {
180namespace stdx {
181
182using ::bsoncxx::v_noabi::stdx::make_unique;
183using ::bsoncxx::v_noabi::stdx::make_unique_for_overwrite;
184
185} // namespace stdx
186} // namespace bsoncxx
187
194
195#if defined(BSONCXX_PRIVATE_DOXYGEN_PREPROCESSOR)
196
197namespace bsoncxx {
198namespace v_noabi {
199namespace stdx {
200
206template <typename T, typename... Args>
207std::unique_ptr<T> make_unique(Args&&... args);
208
214template <typename T>
215std::unique_ptr<T> make_unique(std::size_t count);
216
217} // namespace stdx
218} // namespace v_noabi
219} // namespace bsoncxx
220
221namespace bsoncxx {
222namespace stdx {
223
225template <typename T, typename... Args>
226std::unique_ptr<T> make_unique(Args&&... args);
227
229template <typename T>
230std::unique_ptr<T> make_unique(std::size_t count);
231
232} // namespace stdx
233} // namespace bsoncxx
234
235#endif // defined(BSONCXX_PRIVATE_DOXYGEN_PREPROCESSOR)
The bsoncxx macro guard postlude header.
The bsoncxx macro guard prelude header.
std::unique_ptr< T > make_unique(Args &&... args)
bsoncxx::v_noabi::stdx::make_unique(Args&&... args)
std::unique_ptr< T > make_unique(Args &&... args)
Equivalent to std::make_unique for non-array types.
The top-level namespace within which all bsoncxx library entities are declared.
Provides <type_traits>-related polyfills for internal use.