MongoDB C++ Driver  mongocxx-3.10.2
All Classes Namespaces Functions Typedefs Enumerations Enumerator Friends Pages
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 
38 namespace bsoncxx {
39 namespace v_noabi {
40 namespace stdx {
41 namespace 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.
47 template <typename T>
48 struct 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:
69 template <typename Elem>
70 struct 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:
86 template <typename Elem, std::size_t N>
87 struct make_unique_impl<Elem[N]> {};
88 
89 // References are nonsense:
90 template <typename T>
91 struct make_unique_impl<T&> {};
92 
93 // References are nonsense:
94 template <typename T>
95 struct 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 
105 namespace bsoncxx {
106 namespace v_noabi {
107 namespace 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)
112 using ::std::make_unique;
113 #else
114 
116 template <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>
122 std::unique_ptr<T> make_unique(Args&&... args) {
123  return Impl::make(std::true_type{}, std::forward<Args>(args)...);
124 }
125 
127 template <
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>
133 std::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)
142 using ::std::make_unique_for_overwrite;
143 #else
144 
146 template <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>
150 std::unique_ptr<T> make_unique_for_overwrite() {
151  return Impl::make(std::false_type{});
152 }
153 
155 template <
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>
161 std::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 
175 namespace bsoncxx {
176 namespace stdx {
177 
178 using ::bsoncxx::v_noabi::stdx::make_unique;
179 using ::bsoncxx::v_noabi::stdx::make_unique_for_overwrite;
180 
181 } // namespace stdx
182 } // namespace bsoncxx
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
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
type
An enumeration of each BSON type.
Definition: types.hpp:48
The top-level namespace for bsoncxx library entities.
Definition: element-fwd.hpp:19