MongoDB C++ Driver  mongocxx-3.9.0
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 <cstddef>
18 #include <memory>
19 #include <type_traits>
20 #include <utility>
21 
22 #include <bsoncxx/stdx/type_traits.hpp>
23 
24 #include <bsoncxx/config/prelude.hpp>
25 
26 namespace bsoncxx {
27 inline namespace v_noabi {
28 namespace stdx {
29 
30 namespace detail {
31 
32 // Switch backend of make_unique by the type we are creating.
33 // It would be easier to 'if constexpr' on whether we are an array and whether to direct-init or
34 // value-init, but we don't have if-constexpr and we need it to guard against an uterance of a
35 // possibly-illegal 'new' expression.
36 template <typename T>
37 struct make_unique_impl {
38  // For make_unique:
39  template <typename... Args,
40  // Guard on constructible-from:
41  typename = decltype(new T(std::declval<Args>()...))>
42  static std::unique_ptr<T> make(std::true_type /* direct-init */, Args&&... args) {
43  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
44  }
45 
46  // For make_unique_for_overwrite:
47  template <typename U = T,
48  // Guard on whether T is value-initializable:
49  // (Hide behind a deduced 'U' to defer the evaluation of
50  // this default template argument until overload resolution)
51  typename = decltype(new U)>
52  static std::unique_ptr<T> make(std::false_type /* value-init */) {
53  return std::unique_ptr<T>(new T);
54  }
55 };
56 
57 // For unbounded arrays:
58 template <typename Elem>
59 struct make_unique_impl<Elem[]> {
60  template <typename ShouldDirectInit,
61  // Guard on whether the new-expression will be legal:
62  typename = decltype(new Elem[std::declval<std::size_t>()])>
63  static std::unique_ptr<Elem[]> make(ShouldDirectInit, std::size_t count) {
64  // These can share a function via a plain if, because both new expressions
65  // must be semantically valid
66  if (ShouldDirectInit()) {
67  return std::unique_ptr<Elem[]>(new Elem[count]());
68  } else {
69  return std::unique_ptr<Elem[]>(new Elem[count]);
70  }
71  }
72 };
73 
74 // Bounded arrays are disallowed:
75 template <typename Elem, std::size_t N>
76 struct make_unique_impl<Elem[N]> {};
77 
78 // References are nonsense:
79 template <typename T>
80 struct make_unique_impl<T&> {};
81 
82 // References are nonsense:
83 template <typename T>
84 struct make_unique_impl<T&&> {};
85 
86 } // namespace detail
87 
89 template <typename T,
90  typename... Args,
91  typename Impl = detail::make_unique_impl<T>,
92  typename std::enable_if<!std::is_array<T>::value,
93  decltype(Impl::make(std::true_type{}, std::declval<Args>()...),
94  void())>::type* = nullptr>
95 std::unique_ptr<T> make_unique(Args&&... args) {
96  return Impl::make(std::true_type{}, std::forward<Args>(args)...);
97 }
98 
100 template <
101  typename T,
102  typename Impl = detail::make_unique_impl<T>,
103  typename std::enable_if<std::is_array<T>::value,
104  decltype(Impl::make(std::true_type{}, std::declval<std::size_t>()),
105  void())>::type* = nullptr>
106 std::unique_ptr<T> make_unique(std::size_t count) {
107  return Impl::make(std::true_type{}, count);
108 }
109 
111 template <typename T,
112  typename Impl = detail::make_unique_impl<T>,
113  typename std::enable_if<!std::is_array<T>::value,
114  decltype(Impl::make(std::false_type{}), void())>::type* = nullptr>
115 std::unique_ptr<T> make_unique_for_overwrite() {
116  return Impl::make(std::false_type{});
117 }
118 
120 template <
121  typename T,
122  typename Impl = detail::make_unique_impl<T>,
123  typename std::enable_if<std::is_array<T>::value,
124  decltype(Impl::make(std::false_type{}, std::declval<std::size_t>()),
125  void())>::type* = nullptr>
126 std::unique_ptr<T> make_unique_for_overwrite(std::size_t count) {
127  return Impl::make(std::false_type{}, count);
128 }
129 
130 } // namespace stdx
131 } // namespace v_noabi
132 } // namespace bsoncxx
133 
134 #include <bsoncxx/config/postlude.hpp>
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:95
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:115
type
An enumeration of each BSON type.
Definition: types.hpp:50
The top-level namespace for bsoncxx library entities.
Definition: element.hpp:24