• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_SRC_CORE_UTIL_MANUAL_CONSTRUCTOR_H
20 #define GRPC_SRC_CORE_UTIL_MANUAL_CONSTRUCTOR_H
21 
22 // manually construct a region of memory with some type
23 
24 #include <grpc/support/port_platform.h>
25 #include <stddef.h>
26 
27 #include <utility>
28 
29 #include "src/core/util/construct_destruct.h"
30 
31 namespace grpc_core {
32 
33 // this contains templated helpers needed to implement the ManualConstructors
34 // in this file.
35 namespace manual_ctor_impl {
36 
37 // is_one_of returns true it a class, Member, is present in a variadic list of
38 // classes, List.
39 template <class Member, class... List>
40 class is_one_of;
41 
42 template <class Member, class... List>
43 class is_one_of<Member, Member, List...> {
44  public:
45   static constexpr const bool value = true;
46 };
47 
48 template <class Member, class A, class... List>
49 class is_one_of<Member, A, List...> {
50  public:
51   static constexpr const bool value = is_one_of<Member, List...>::value;
52 };
53 
54 template <class Member>
55 class is_one_of<Member> {
56  public:
57   static constexpr const bool value = false;
58 };
59 
60 // max_size_of returns sizeof(Type) for the largest type in the variadic list
61 // of classes, Types.
62 template <class... Types>
63 class max_size_of;
64 
65 template <class A>
66 class max_size_of<A> {
67  public:
68   static constexpr const size_t value = sizeof(A);
69 };
70 
71 template <class A, class... B>
72 class max_size_of<A, B...> {
73  public:
74   static constexpr const size_t value = sizeof(A) > max_size_of<B...>::value
75                                             ? sizeof(A)
76                                             : max_size_of<B...>::value;
77 };
78 
79 // max_size_of returns alignof(Type) for the largest type in the variadic list
80 // of classes, Types.
81 template <class... Types>
82 class max_align_of;
83 
84 template <class A>
85 class max_align_of<A> {
86  public:
87   static constexpr const size_t value = alignof(A);
88 };
89 
90 template <class A, class... B>
91 class max_align_of<A, B...> {
92  public:
93   static constexpr const size_t value = alignof(A) > max_align_of<B...>::value
94                                             ? alignof(A)
95                                             : max_align_of<B...>::value;
96 };
97 
98 }  // namespace manual_ctor_impl
99 
100 template <typename Type>
101 class ManualConstructor {
102  public:
103   // No constructor or destructor because one of the most useful uses of
104   // this class is as part of a union, and members of a union could not have
105   // constructors or destructors till C++11.  And, anyway, the whole point of
106   // this class is to bypass constructor and destructor.
107 
get()108   Type* get() { return reinterpret_cast<Type*>(&space_); }
get()109   const Type* get() const { return reinterpret_cast<const Type*>(&space_); }
110 
111   Type* operator->() { return get(); }
112   const Type* operator->() const { return get(); }
113 
114   Type& operator*() { return *get(); }
115   const Type& operator*() const { return *get(); }
116 
Init()117   void Init() { Construct(get()); }
118 
119   // Init() constructs the Type instance using the given arguments
120   // (which are forwarded to Type's constructor).
121   //
122   // Note that Init() with no arguments performs default-initialization,
123   // not zero-initialization (i.e it behaves the same as "new Type;", not
124   // "new Type();"), so it will leave non-class types uninitialized.
125   template <typename... Ts>
Init(Ts &&...args)126   void Init(Ts&&... args) {
127     Construct(get(), std::forward<Ts>(args)...);
128   }
129 
130   // Init() that is equivalent to copy and move construction.
131   // Enables usage like this:
132   //   ManualConstructor<std::vector<int>> v;
133   //   v.Init({1, 2, 3});
Init(const Type & x)134   void Init(const Type& x) { Construct(get(), x); }
Init(Type && x)135   void Init(Type&& x) { Construct(get(), std::forward<Type>(x)); }
136 
Destroy()137   void Destroy() { Destruct(get()); }
138 
139  private:
140   alignas(Type) char space_[sizeof(Type)];
141 };
142 
143 }  // namespace grpc_core
144 
145 #endif  // GRPC_SRC_CORE_UTIL_MANUAL_CONSTRUCTOR_H
146