make_unique.h
5.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: make_unique.h
// -----------------------------------------------------------------------------
//
// This header file contains utility functions for managing the creation and
// conversion of smart pointers. This file is an extension to the C++
// standard <memory> library header file.
/* Modifications Copyright (c) Microsoft. */
#pragma once
#include <cstddef>
#include <limits>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
namespace onnxruntime {
template <typename T>
using remove_extent_t = typename std::remove_extent<T>::type;
namespace memory_internal {
// Traits to select proper overload and return type for `absl::make_unique<>`.
template <typename T>
struct MakeUniqueResult {
using scalar = std::unique_ptr<T>;
};
template <typename T>
struct MakeUniqueResult<T[]> {
using array = std::unique_ptr<T[]>;
};
template <typename T, size_t N>
struct MakeUniqueResult<T[N]> {
using invalid = void;
};
} // namespace memory_internal
// gcc 4.8 has __cplusplus at 201301 but doesn't define make_unique. Other
// supported compilers either just define __cplusplus as 201103 but have
// make_unique (msvc), or have make_unique whenever __cplusplus > 201103 (clang)
#if (__cplusplus > 201103L || defined(_MSC_VER)) && \
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8)
using std::make_unique;
#else
// -----------------------------------------------------------------------------
// Function Template: make_unique<T>()
// -----------------------------------------------------------------------------
//
// Creates a `std::unique_ptr<>`, while avoiding issues creating temporaries
// during the construction process. `absl::make_unique<>` also avoids redundant
// type declarations, by avoiding the need to explicitly use the `new` operator.
//
// This implementation of `absl::make_unique<>` is designed for C++11 code and
// will be replaced in C++14 by the equivalent `std::make_unique<>` abstraction.
// `absl::make_unique<>` is designed to be 100% compatible with
// `std::make_unique<>` so that the eventual migration will involve a simple
// rename operation.
//
// For more background on why `std::unique_ptr<T>(new T(a,b))` is problematic,
// see Herb Sutter's explanation on
// (Exception-Safe Function Calls)[https://herbsutter.com/gotw/_102/].
// (In general, reviewers should treat `new T(a,b)` with scrutiny.)
//
// Example usage:
//
// auto p = make_unique<X>(args...); // 'p' is a std::unique_ptr<X>
// auto pa = make_unique<X[]>(5); // 'pa' is a std::unique_ptr<X[]>
//
// Three overloads of `absl::make_unique` are required:
//
// - For non-array T:
//
// Allocates a T with `new T(std::forward<Args> args...)`,
// forwarding all `args` to T's constructor.
// Returns a `std::unique_ptr<T>` owning that object.
//
// - For an array of unknown bounds T[]:
//
// `absl::make_unique<>` will allocate an array T of type U[] with
// `new U[n]()` and return a `std::unique_ptr<U[]>` owning that array.
//
// Note that 'U[n]()' is different from 'U[n]', and elements will be
// value-initialized. Note as well that `std::unique_ptr` will perform its
// own destruction of the array elements upon leaving scope, even though
// the array [] does not have a default destructor.
//
// NOTE: an array of unknown bounds T[] may still be (and often will be)
// initialized to have a size, and will still use this overload. E.g:
//
// auto my_array = absl::make_unique<int[]>(10);
//
// - For an array of known bounds T[N]:
//
// `absl::make_unique<>` is deleted (like with `std::make_unique<>`) as
// this overload is not useful.
//
// NOTE: an array of known bounds T[N] is not considered a useful
// construction, and may cause undefined behavior in templates. E.g:
//
// auto my_array = absl::make_unique<int[10]>();
//
// In those cases, of course, you can still use the overload above and
// simply initialize it to its desired size:
//
// auto my_array = absl::make_unique<int[]>(10);
// `absl::make_unique` overload for non-array types.
template <typename T, typename... Args>
typename memory_internal::MakeUniqueResult<T>::scalar make_unique(
Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
// `absl::make_unique` overload for an array T[] of unknown bounds.
// The array allocation needs to use the `new T[size]` form and cannot take
// element constructor arguments. The `std::unique_ptr` will manage destructing
// these array elements.
template <typename T>
typename memory_internal::MakeUniqueResult<T>::array make_unique(size_t n) {
return std::unique_ptr<T>(new typename onnxruntime::remove_extent_t<T>[n]());
}
// `absl::make_unique` overload for an array T[N] of known bounds.
// This construction will be rejected.
template <typename T, typename... Args>
typename memory_internal::MakeUniqueResult<T>::invalid make_unique(
Args&&... /* args */) = delete;
#endif
}