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