MongoDB C++ Driver mongocxx-3.10.1
Loading...
Searching...
No Matches
make_unique.hpp
1// Copyright 2014 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
19#include <bsoncxx/config/prelude.hpp>
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
36#include <bsoncxx/stdx/type_traits.hpp>
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
116template <typename T,
117 typename... Args,
118 typename Impl = detail::make_unique_impl<T>,
119 typename std::enable_if<!std::is_array<T>::value,
120 decltype(Impl::make(std::true_type{}, std::declval<Args>()...),
121 void())>::type* = nullptr>
122std::unique_ptr<T> make_unique(Args&&... args) {
123 return Impl::make(std::true_type{}, std::forward<Args>(args)...);
124}
125
127template <
128 typename T,
129 typename Impl = detail::make_unique_impl<T>,
130 typename std::enable_if<std::is_array<T>::value,
131 decltype(Impl::make(std::true_type{}, std::declval<std::size_t>()),
132 void())>::type* = nullptr>
133std::unique_ptr<T> make_unique(std::size_t count) {
134 return Impl::make(std::true_type{}, count);
135}
136
137#endif
138
139// Unlike other C++17 polyfill features, this is a C++20 feature.
140// Use feature testing rather than polyfill library selection macros.
141#if defined(__cpp_lib_smart_ptr_for_overwrite)
142using ::std::make_unique_for_overwrite;
143#else
144
146template <typename T,
147 typename Impl = detail::make_unique_impl<T>,
148 typename std::enable_if<!std::is_array<T>::value,
149 decltype(Impl::make(std::false_type{}), void())>::type* = nullptr>
150std::unique_ptr<T> make_unique_for_overwrite() {
151 return Impl::make(std::false_type{});
152}
153
155template <
156 typename T,
157 typename Impl = detail::make_unique_impl<T>,
158 typename std::enable_if<std::is_array<T>::value,
159 decltype(Impl::make(std::false_type{}, std::declval<std::size_t>()),
160 void())>::type* = nullptr>
161std::unique_ptr<T> make_unique_for_overwrite(std::size_t count) {
162 return Impl::make(std::false_type{}, count);
163}
164
165#endif
166
167} // namespace stdx
168} // namespace v_noabi
169} // namespace bsoncxx
170
171#pragma pop_macro("BSONCXX_DETAIL_USE_STD_MAKE_UNIQUE")
172
173#include <bsoncxx/config/postlude.hpp>
174
175namespace bsoncxx {
176namespace stdx {
177
178using ::bsoncxx::v_noabi::stdx::make_unique;
179using ::bsoncxx::v_noabi::stdx::make_unique_for_overwrite;
180
181} // namespace stdx
182} // namespace bsoncxx
std::unique_ptr< T > make_unique_for_overwrite()
Equivalent to std::make_unique_for_overwrite<T>() where T is a non-array type.
Definition make_unique.hpp:150
std::unique_ptr< T > make_unique(Args &&... args)
Equivalent to std::make_unique<T>(args...) where T is a non-array type.
Definition make_unique.hpp:122
The top-level namespace for bsoncxx library entities.
Definition element-fwd.hpp:19