MongoDB C++ Driver current
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 <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
26namespace bsoncxx {
27inline namespace v_noabi {
28namespace stdx {
29
30namespace 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.
36template <typename T>
37struct 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:
58template <typename Elem>
59struct 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:
75template <typename Elem, std::size_t N>
76struct make_unique_impl<Elem[N]> {};
77
78// References are nonsense:
79template <typename T>
80struct make_unique_impl<T&> {};
81
82// References are nonsense:
83template <typename T>
84struct make_unique_impl<T&&> {};
85
86} // namespace detail
87
89template <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>
95std::unique_ptr<T> make_unique(Args&&... args) {
96 return Impl::make(std::true_type{}, std::forward<Args>(args)...);
97}
98
100template <
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>
106std::unique_ptr<T> make_unique(std::size_t count) {
107 return Impl::make(std::true_type{}, count);
108}
109
111template <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>
115std::unique_ptr<T> make_unique_for_overwrite() {
116 return Impl::make(std::false_type{});
117}
118
120template <
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>
126std::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_for_overwrite()
Equivalent to std::make_unique_for_overwrite<T>() where T is a non-array type.
Definition make_unique.hpp:115
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
type
An enumeration of each BSON type.
Definition types.hpp:50
The top-level namespace for bsoncxx library entities.
Definition element.hpp:24