siplasplas
A library for C++ reflection and introspection
typeinfo.hpp
1 #ifndef SIPLASPLAS_TYPEERASURE_TYPEINFO_HPP
2 #define SIPLASPLAS_TYPEERASURE_TYPEINFO_HPP
3 
4 #include "features/valuesemantics.hpp"
5 #include <siplasplas/utility/memory_manip.hpp>
6 #include <siplasplas/utility/meta.hpp>
7 #include <siplasplas/utility/function_traits.hpp>
8 
9 namespace cpp
10 {
11 
12 namespace typeerasure
13 {
14 
15 namespace detail
16 {
17 
22 enum class ValueSemanticsOperation : std::size_t
23 {
24  COPY_CONSTRUCT = 0,
25  MOVE_CONSTRUCT = 1,
26  COPY_ASSIGN = 2,
27  MOVE_ASSIGN = 3,
28  DESTROY = 4
29 };
30 
31 using ValueSemanticsOperationFunction = void(*)(void*, const void*);
32 
54 template<typename T>
55 ValueSemanticsOperationFunction valueSemanticsOperation(ValueSemanticsOperation operation)
56 {
57  static ValueSemanticsOperationFunction operations[] = {
58  +[](void* object, const void* other) {
59  features::CopyConstructible::apply<T>(object, other);
60  },
61  +[](void* object, const void* other) {
62  features::MoveConstructible::apply<T>(object, const_cast<void*>(other));
63  },
64  +[](void* object, const void* other) {
65  features::CopyAssignable::apply<T>(object, other);
66  },
67  +[](void* object, const void* other) {
68  features::MoveAssignable::apply<T>(object, const_cast<void*>(other));
69  },
70  +[](void* object, const void*) {
71  features::Destructible::apply<T>(object);
72  }
73  };
74 
75  return operations[static_cast<std::size_t>(operation)];
76 }
77 
78 using ValueSemantics = decltype(&valueSemanticsOperation<int>);
79 
80 }
81 
108 class TypeInfo
109 {
110 public:
114  detail::ValueSemantics semantics() const
115  {
116 #if UINTPTR_MAX == UINT64_MAX // See constructor bellow
117  return cpp::detail::untagPointer(_semantics);
118 #else
119  return _semantics;
120 #endif
121  }
122 
126  std::size_t sizeOf() const
127  {
128  return _sizeOf;
129  }
130 
134  const char* typeName() const
135  {
136  return _typeId.name().c_str();
137  }
138 
142  bool isPointer() const
143  {
144  return _isPointer;
145  }
146 
151  detail::ValueSemanticsOperationFunction semantics(detail::ValueSemanticsOperation operation) const
152  {
153  return semantics()(operation);
154  }
155 
163  void copyConstruct(void* where, const void* other) const
164  {
165  semantics(detail::ValueSemanticsOperation::COPY_CONSTRUCT)(where, other);
166  }
167 
176  void moveConstruct(void* where, void* other) const
177  {
178  semantics(detail::ValueSemanticsOperation::MOVE_CONSTRUCT)(where, const_cast<const void*>(other));
179  }
180 
188  void copyAssign(void* where, const void* other) const
189  {
190  semantics(detail::ValueSemanticsOperation::COPY_ASSIGN)(where, other);
191  }
192 
201  void moveAssign(void* where, void* other) const
202  {
203  semantics(detail::ValueSemanticsOperation::MOVE_ASSIGN)(where, const_cast<const void*>(other));
204  }
205 
212  void destroy(void* where) const
213  {
214  if(!isPointer())
215  {
216  semantics(detail::ValueSemanticsOperation::DESTROY)(where, nullptr);
217  }
218  }
219 
223  template<typename T>
224  static constexpr TypeInfo get()
225  {
226  return TypeInfo{meta::identity<T>()};
227  }
228 
229  friend constexpr bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
230  {
231  return lhs._semantics == rhs._semantics;
232  }
233 
234  friend constexpr bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs)
235  {
236  return !(lhs == rhs);
237  }
238 
239 private:
240  template<typename T>
241  constexpr TypeInfo(meta::identity<T>) :
242 // If virtual addresses have 64 bits, use a use a tagged pointer to store the alignment,
243 // else use an extra member
244 #if UINTPTR_MAX == UINT64_MAX
245  _semantics{cpp::detail::tagPointer(&detail::valueSemanticsOperation<T>, alignof(T))},
246  _sizeOf{sizeof(T)},
247  _typeId{ctti::type_id<T>()},
248  _isPointer{
249  std::is_pointer<T>::value &&
250  cpp::function_kind<T>() != cpp::FunctionKind::FREE_FUNCTION
251  }
252  {
253  static_assert(alignof(T) < (1 << 16), "Alignment of T cannot be tagged in a pointer, its value overflows a 16 bit unsigned integer");
254  }
255 
256 public:
260  std::size_t alignment() const
261  {
262  return cpp::detail::readTaggedPointer(_semantics);
263  }
264 
265 private:
266 #else
267  _semantics{&valueSemanticsOperation<T>},
268  _alignment{alignof(T)},
269  _sizeOf{sizeof(T)},
270  _typeId{ctti::type_id<T>()},
271  _isPointer{
272  std::is_pointer<T>::value &&
273  cpp::function_kind<T>() != cpp::FunctionKind::FREE_FUNCTION
274  }
275  {}
276 
277 public:
281  constexpr std::size_t alignment() const
282  {
283  return _alignment;
284  }
285 
286 private:
287  std::size_t _alignment;
288 #endif // if not 64 bit
289  detail::ValueSemantics _semantics;
290  std::size_t _sizeOf;
291  ctti::type_id_t _typeId;
292  bool _isPointer;
293 };
294 
295 }
296 
297 }
298 
299 #endif // SIPLASPLAS_TYPEERASURE_TYPEINFO_HPP
ValueSemanticsOperation
Represents a value semantics operation. See valueSemanticsOperation()
Definition: typeinfo.hpp:22
T * untagPointer(T *pointer)
Untags a pointer.
Definition: memory_manip.hpp:220
void moveConstruct(void *where, void *other) const
Move constructs values of the type If the passed arguments are not of the represented type...
Definition: typeinfo.hpp:176
Definition: canary_allocator.hpp:7
detail::ValueSemanticsOperationFunction semantics(detail::ValueSemanticsOperation operation) const
Returns the function implementing the given valuesemantics operation for the type.
Definition: typeinfo.hpp:151
ValueSemanticsOperationFunction valueSemanticsOperation(ValueSemanticsOperation operation)
Implements a type-erased interface for the value semantics features of a type T.
Definition: typeinfo.hpp:55
detail::ValueSemantics semantics() const
Retuns the type-erased semantics of the type. See valueSemantics().
Definition: typeinfo.hpp:114
std::size_t alignment() const
returns the alignment of the type
Definition: typeinfo.hpp:260
void copyConstruct(void *where, const void *other) const
Copy constructs values of the type If the passed arguments are not of the represented type...
Definition: typeinfo.hpp:163
void destroy(void *where) const
Destroys objects of the type If the passed arguments are not of the represented type, the behavior is undefined.
Definition: typeinfo.hpp:212
void copyAssign(void *where, const void *other) const
Move assigns values of the type If the passed arguments are not of the represented type...
Definition: typeinfo.hpp:188
bool isPointer() const
Checks if the type is a pointer type.
Definition: typeinfo.hpp:142
std::uint16_t readTaggedPointer(T *pointer)
Reads the data stored in a tagged pointer.
Definition: memory_manip.hpp:260
const char * typeName() const
Returns the name of the type.
Definition: typeinfo.hpp:134
void moveAssign(void *where, void *other) const
Move assigns values of the type If the passed arguments are not of the represented type...
Definition: typeinfo.hpp:201
Contains minimal information to execute the value semantics operations of a type. ...
Definition: typeinfo.hpp:108
T * tagPointer(T *pointer, U data)
Tags a pointer with the specified data.
Definition: memory_manip.hpp:177
std::size_t sizeOf() const
Returns the size of the type.
Definition: typeinfo.hpp:126