3 * Copyright 2016 gRPC authors.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #ifndef GRPC_CORE_LIB_GPRPP_MANUAL_CONSTRUCTOR_H
20 #define GRPC_CORE_LIB_GPRPP_MANUAL_CONSTRUCTOR_H
22 // manually construct a region of memory with some type
24 #include <grpc/support/port_platform.h>
29 #include <type_traits>
32 #include <grpc/support/log.h>
36 // this contains templated helpers needed to implement the ManualConstructors
38 namespace manual_ctor_impl {
40 // is_one_of returns true it a class, Member, is present in a variadic list of
42 template <class Member, class... List>
45 template <class Member, class... List>
46 class is_one_of<Member, Member, List...> {
48 static constexpr const bool value = true;
51 template <class Member, class A, class... List>
52 class is_one_of<Member, A, List...> {
54 static constexpr const bool value = is_one_of<Member, List...>::value;
57 template <class Member>
58 class is_one_of<Member> {
60 static constexpr const bool value = false;
63 // max_size_of returns sizeof(Type) for the largest type in the variadic list
65 template <class... Types>
69 class max_size_of<A> {
71 static constexpr const size_t value = sizeof(A);
74 template <class A, class... B>
75 class max_size_of<A, B...> {
77 static constexpr const size_t value = sizeof(A) > max_size_of<B...>::value
79 : max_size_of<B...>::value;
82 // max_size_of returns alignof(Type) for the largest type in the variadic list
84 template <class... Types>
88 class max_align_of<A> {
90 static constexpr const size_t value = alignof(A);
93 template <class A, class... B>
94 class max_align_of<A, B...> {
96 static constexpr const size_t value = alignof(A) > max_align_of<B...>::value
98 : max_align_of<B...>::value;
101 } // namespace manual_ctor_impl
103 template <class BaseType, class... DerivedTypes>
104 class PolymorphicManualConstructor {
106 // No constructor or destructor because one of the most useful uses of
107 // this class is as part of a union, and members of a union could not have
108 // constructors or destructors till C++11. And, anyway, the whole point of
109 // this class is to bypass constructor and destructor.
111 BaseType* get() { return reinterpret_cast<BaseType*>(&space_); }
112 const BaseType* get() const {
113 return reinterpret_cast<const BaseType*>(&space_);
116 BaseType* operator->() { return get(); }
117 const BaseType* operator->() const { return get(); }
119 BaseType& operator*() { return *get(); }
120 const BaseType& operator*() const { return *get(); }
122 template <class DerivedType>
124 FinishInit(new (&space_) DerivedType);
127 // Init() constructs the Type instance using the given arguments
128 // (which are forwarded to Type's constructor).
130 // Note that Init() with no arguments performs default-initialization,
131 // not zero-initialization (i.e it behaves the same as "new Type;", not
132 // "new Type();"), so it will leave non-class types uninitialized.
133 template <class DerivedType, typename... Ts>
134 void Init(Ts&&... args) {
135 FinishInit(new (&space_) DerivedType(std::forward<Ts>(args)...));
138 // Init() that is equivalent to copy and move construction.
139 // Enables usage like this:
140 // ManualConstructor<std::vector<int>> v;
141 // v.Init({1, 2, 3});
142 template <class DerivedType>
143 void Init(const DerivedType& x) {
144 FinishInit(new (&space_) DerivedType(x));
146 template <class DerivedType>
147 void Init(DerivedType&& x) {
148 FinishInit(new (&space_) DerivedType(std::forward<DerivedType>(x)));
151 void Destroy() { get()->~BaseType(); }
154 template <class DerivedType>
155 void FinishInit(DerivedType* p) {
157 manual_ctor_impl::is_one_of<DerivedType, DerivedTypes...>::value,
158 "DerivedType must be one of the predeclared DerivedTypes");
159 GPR_ASSERT(static_cast<BaseType*>(p) == p);
162 typename std::aligned_storage<
163 grpc_core::manual_ctor_impl::max_size_of<DerivedTypes...>::value,
164 grpc_core::manual_ctor_impl::max_align_of<DerivedTypes...>::value>::type
168 template <typename Type>
169 class ManualConstructor {
171 // No constructor or destructor because one of the most useful uses of
172 // this class is as part of a union, and members of a union could not have
173 // constructors or destructors till C++11. And, anyway, the whole point of
174 // this class is to bypass constructor and destructor.
176 Type* get() { return reinterpret_cast<Type*>(&space_); }
177 const Type* get() const { return reinterpret_cast<const Type*>(&space_); }
179 Type* operator->() { return get(); }
180 const Type* operator->() const { return get(); }
182 Type& operator*() { return *get(); }
183 const Type& operator*() const { return *get(); }
185 void Init() { new (&space_) Type; }
187 // Init() constructs the Type instance using the given arguments
188 // (which are forwarded to Type's constructor).
190 // Note that Init() with no arguments performs default-initialization,
191 // not zero-initialization (i.e it behaves the same as "new Type;", not
192 // "new Type();"), so it will leave non-class types uninitialized.
193 template <typename... Ts>
194 void Init(Ts&&... args) {
195 new (&space_) Type(std::forward<Ts>(args)...);
198 // Init() that is equivalent to copy and move construction.
199 // Enables usage like this:
200 // ManualConstructor<std::vector<int>> v;
201 // v.Init({1, 2, 3});
202 void Init(const Type& x) { new (&space_) Type(x); }
203 void Init(Type&& x) { new (&space_) Type(std::move(x)); }
205 void Destroy() { get()->~Type(); }
208 typename std::aligned_storage<sizeof(Type), alignof(Type)>::type space_;
211 } // namespace grpc_core
213 #endif // GRPC_CORE_LIB_GPRPP_MANUAL_CONSTRUCTOR_H