GRPC Core  9.0.0
manual_constructor.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright 2016 gRPC authors.
4  *
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
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  */
18 
19 #ifndef GRPC_CORE_LIB_GPRPP_MANUAL_CONSTRUCTOR_H
20 #define GRPC_CORE_LIB_GPRPP_MANUAL_CONSTRUCTOR_H
21 
22 // manually construct a region of memory with some type
23 
25 
26 #include <stddef.h>
27 #include <stdlib.h>
28 #include <new>
29 #include <type_traits>
30 #include <utility>
31 
32 #include <grpc/support/log.h>
33 
34 namespace grpc_core {
35 
36 // this contains templated helpers needed to implement the ManualConstructors
37 // in this file.
38 namespace manual_ctor_impl {
39 
40 // is_one_of returns true it a class, Member, is present in a variadic list of
41 // classes, List.
42 template <class Member, class... List>
43 class is_one_of;
44 
45 template <class Member, class... List>
46 class is_one_of<Member, Member, List...> {
47  public:
48  static constexpr const bool value = true;
49 };
50 
51 template <class Member, class A, class... List>
52 class is_one_of<Member, A, List...> {
53  public:
54  static constexpr const bool value = is_one_of<Member, List...>::value;
55 };
56 
57 template <class Member>
58 class is_one_of<Member> {
59  public:
60  static constexpr const bool value = false;
61 };
62 
63 // max_size_of returns sizeof(Type) for the largest type in the variadic list
64 // of classes, Types.
65 template <class... Types>
67 
68 template <class A>
69 class max_size_of<A> {
70  public:
71  static constexpr const size_t value = sizeof(A);
72 };
73 
74 template <class A, class... B>
75 class max_size_of<A, B...> {
76  public:
77  static constexpr const size_t value = sizeof(A) > max_size_of<B...>::value
78  ? sizeof(A)
79  : max_size_of<B...>::value;
80 };
81 
82 // max_size_of returns alignof(Type) for the largest type in the variadic list
83 // of classes, Types.
84 template <class... Types>
86 
87 template <class A>
88 class max_align_of<A> {
89  public:
90  static constexpr const size_t value = alignof(A);
91 };
92 
93 template <class A, class... B>
94 class max_align_of<A, B...> {
95  public:
96  static constexpr const size_t value = alignof(A) > max_align_of<B...>::value
97  ? alignof(A)
98  : max_align_of<B...>::value;
99 };
100 
101 } // namespace manual_ctor_impl
102 
103 template <class BaseType, class... DerivedTypes>
105  public:
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.
110 
111  BaseType* get() { return reinterpret_cast<BaseType*>(&space_); }
112  const BaseType* get() const {
113  return reinterpret_cast<const BaseType*>(&space_);
114  }
115 
116  BaseType* operator->() { return get(); }
117  const BaseType* operator->() const { return get(); }
118 
119  BaseType& operator*() { return *get(); }
120  const BaseType& operator*() const { return *get(); }
121 
122  template <class DerivedType>
123  void Init() {
124  FinishInit(new (&space_) DerivedType);
125  }
126 
127  // Init() constructs the Type instance using the given arguments
128  // (which are forwarded to Type's constructor).
129  //
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)...));
136  }
137 
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));
145  }
146  template <class DerivedType>
147  void Init(DerivedType&& x) {
148  FinishInit(new (&space_) DerivedType(std::move(x)));
149  }
150 
151  void Destroy() { get()->~BaseType(); }
152 
153  private:
154  template <class DerivedType>
155  void FinishInit(DerivedType* p) {
156  static_assert(
158  "DerivedType must be one of the predeclared DerivedTypes");
159  GPR_ASSERT(static_cast<BaseType*>(p) == p);
160  }
161 
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
165  space_;
166 };
167 
168 template <typename Type>
170  public:
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.
175 
176  Type* get() { return reinterpret_cast<Type*>(&space_); }
177  const Type* get() const { return reinterpret_cast<const Type*>(&space_); }
178 
179  Type* operator->() { return get(); }
180  const Type* operator->() const { return get(); }
181 
182  Type& operator*() { return *get(); }
183  const Type& operator*() const { return *get(); }
184 
185  void Init() { new (&space_) Type; }
186 
187  // Init() constructs the Type instance using the given arguments
188  // (which are forwarded to Type's constructor).
189  //
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)...);
196  }
197 
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)); }
204 
205  void Destroy() { get()->~Type(); }
206 
207  private:
208  typename std::aligned_storage<sizeof(Type), alignof(Type)>::type space_;
209 };
210 
211 } // namespace grpc_core
212 
213 #endif
Definition: manual_constructor.h:169
const Type * operator->() const
Definition: manual_constructor.h:180
Type & operator*()
Definition: manual_constructor.h:182
const Type & operator*() const
Definition: manual_constructor.h:183
void Destroy()
Definition: manual_constructor.h:205
Type * operator->()
Definition: manual_constructor.h:179
Type * get()
Definition: manual_constructor.h:176
void Init(Ts &&... args)
Definition: manual_constructor.h:194
const Type * get() const
Definition: manual_constructor.h:177
void Init(const Type &x)
Definition: manual_constructor.h:202
void Init()
Definition: manual_constructor.h:185
void Init(Type &&x)
Definition: manual_constructor.h:203
Definition: manual_constructor.h:104
void Init(const DerivedType &x)
Definition: manual_constructor.h:143
BaseType * operator->()
Definition: manual_constructor.h:116
void Destroy()
Definition: manual_constructor.h:151
void Init(Ts &&... args)
Definition: manual_constructor.h:134
BaseType & operator*()
Definition: manual_constructor.h:119
void Init(DerivedType &&x)
Definition: manual_constructor.h:147
const BaseType & operator*() const
Definition: manual_constructor.h:120
const BaseType * operator->() const
Definition: manual_constructor.h:117
const BaseType * get() const
Definition: manual_constructor.h:112
void Init()
Definition: manual_constructor.h:123
BaseType * get()
Definition: manual_constructor.h:111
Definition: manual_constructor.h:43
Definition: manual_constructor.h:85
Definition: manual_constructor.h:66
#define GPR_ASSERT(x)
abort() the process if x is zero, having written a line to the log.
Definition: log.h:94
Round Robin Policy.
Definition: backend_metric.cc:24