GEGELATI
untypedSharedPtr.h
1
37#ifndef UNTYPED_SHARED_PTR_H
38#define UNTYPED_SHARED_PTR_H
39
40#include <functional>
41#include <memory>
42#include <stdexcept>
43#include <string>
44#include <type_traits>
45
46namespace Data {
47
72 {
73 public:
77 struct Concept
78 {
80 virtual ~Concept() = default;
82 virtual const std::type_info& getType() const = 0;
84 virtual const std::type_info& getPtrType() const = 0;
85 };
86
95 template <typename T> struct Model : Concept
96 {
98 using ELEM_TYPE = typename std::remove_all_extents<T>::type;
99
100 public:
103 template <typename Deleter>
104 Model(T* t, Deleter func) : sharedPtr(t, func)
105 {
106 }
107
111 template <typename U, typename _ = typename std::enable_if<
112 std::is_array<T>::value, U>::type>
113 Model(U* p) : sharedPtr(p, std::default_delete<T>()){};
114
116 const std::type_info& getType() const override
117 {
118 return typeid(T);
119 }
120
122 const std::type_info& getPtrType() const override
123 {
124 return typeid(sharedPtr.get());
125 }
126
128 std::shared_ptr<ELEM_TYPE> sharedPtr;
129 };
130
135
181 template <typename T, class Deleter = std::default_delete<T>>
182 UntypedSharedPtr(T* obj, Deleter func = Deleter())
183 : sharedPtrContainer(std::make_shared<Model<T>>(obj, func)){};
184
199 UntypedSharedPtr(std::shared_ptr<Concept> concept)
200 : sharedPtrContainer(concept){};
201
227 const std::type_info& getType() const
228 {
229 return sharedPtrContainer->getType();
230 }
231
257 const std::type_info& getPtrType() const
258 {
259 return sharedPtrContainer->getPtrType();
260 }
261
306 template <typename T>
307 std::shared_ptr<std::remove_all_extents_t<T>> getSharedPointer() const
308 {
309 const auto& templateType = typeid(T);
310 const auto& templateTypeNoConst = typeid(std::remove_const_t<T>);
311 const auto& ownType = this->getType();
312 const auto& templatePtrType = typeid(T*);
313 const auto& templatePtrTypeNoConst =
314 typeid(std::remove_const_t<T>*);
315 const auto& ownPtrType = this->getPtrType();
316
317 // If pointer types are identical (which includes const qualifier),
318 // go for it. Unless non-pointers types are different, which may be
319 // the case for arrays
320 if (ownPtrType == templatePtrType && templateType == ownType) {
321 std::shared_ptr<const Model<T>> typedPtr =
322 std::dynamic_pointer_cast<const Model<T>>(
323 this->sharedPtrContainer);
324 if (typedPtr != NULL) {
325 return typedPtr->sharedPtr;
326 }
327 }
328
329 // If pointer types are identical when loosing const qualifier of
330 // function template type, go for it. Unless non-pointers types are
331 // different, which may be the case for arrays
332 if (ownPtrType == templatePtrTypeNoConst &&
333 templateType == ownType) {
334 std::shared_ptr<const Model<std::remove_const_t<T>>> typedPtr =
335 std::dynamic_pointer_cast<
337 this->sharedPtrContainer);
338 if (typedPtr != NULL) {
339 return typedPtr->sharedPtr;
340 }
341 }
342
343 // If template type and owntype are the same, go for it.
344 // (it is not the first tested case because constness is lost in
345 // template type and own type.
346 if (templateType == ownType) {
347 std::shared_ptr<const Model<T>> typedPtr =
348 std::dynamic_pointer_cast<const Model<T>>(
349 this->sharedPtrContainer);
350 if (typedPtr != NULL) {
351 return typedPtr->sharedPtr;
352 }
353 }
354
355 // If template type and owntype are identical when loosing const
356 // qualifier of function template type, go for it. (it is not the
357 // first tested case because constness is lost in template type and
358 // own type.
359 if (templateTypeNoConst == ownType) {
360 std::shared_ptr<const Model<std::remove_const_t<T>>> typedPtr =
361 std::dynamic_pointer_cast<
363 this->sharedPtrContainer);
364 if (typedPtr != NULL) {
365 return typedPtr->sharedPtr;
366 }
367 }
368
369 // Type mismatch
370 std::string msg("Cannot convert ");
371 msg.append(ownPtrType.name());
372 msg.append(" into ");
373 msg.append(templatePtrType.name());
374 msg.append(".");
375
376 throw std::runtime_error(msg);
377 }
378
390 template <typename T> static std::function<void(T*)> emptyDestructor()
391 {
392 return [](T* ptr) {};
393 };
394
399 std::shared_ptr<const Concept> sharedPtrContainer;
400 };
401} // namespace Data
402#endif // !UNTYPED_SHARED_PTR_H
Class behaving as a std::shared_ptr whose type is not templated.
Definition: untypedSharedPtr.h:72
const std::type_info & getType() const
Accessor to the type of data stored in the UntypedSharedPtr.
Definition: untypedSharedPtr.h:227
std::shared_ptr< const Concept > sharedPtrContainer
Shared container containing the data structure containing the actual std::shared_ptr.
Definition: untypedSharedPtr.h:393
const std::type_info & getPtrType() const
Accessor to the pointer type of data stored in the UntypedSharedPtr.
Definition: untypedSharedPtr.h:257
UntypedSharedPtr(std::shared_ptr< Concept > concept)
Constructor from an existing Concept.
Definition: untypedSharedPtr.h:199
UntypedSharedPtr()=delete
Deleted default constructor.
std::shared_ptr< std::remove_all_extents_t< T > > getSharedPointer() const
Get the shared_ptr store in the UntypedSharedPtr.
Definition: untypedSharedPtr.h:307
UntypedSharedPtr(T *obj, Deleter func=Deleter())
Main constructor of the UntypedSharedPtr class.
Definition: untypedSharedPtr.h:182
static std::function< void(T *)> emptyDestructor()
Get an empty destructor function for any type.
Definition: untypedSharedPtr.h:390
Definition: array2DWrapper.h:44
Internal structure of the type erasure pattern.
Definition: untypedSharedPtr.h:78
virtual const std::type_info & getPtrType() const =0
Polymorphic getPtrType() function.
virtual ~Concept()=default
Default deleter made virtual to activate polyphormism.
virtual const std::type_info & getType() const =0
Polymorphic getType() function.
Internal templated structure of the type erasure pattern.
Definition: untypedSharedPtr.h:96
Model(T *t, Deleter func)
Definition: untypedSharedPtr.h:104
Model(U *p)
Definition: untypedSharedPtr.h:113
typename std::remove_all_extents< T >::type ELEM_TYPE
Raw type of the element stored in the shared_ptr.
Definition: untypedSharedPtr.h:98
const std::type_info & getPtrType() const override
Polymorphic getPtrType() function.
Definition: untypedSharedPtr.h:122
std::shared_ptr< ELEM_TYPE > sharedPtr
std::shared_ptr of the UntypedSharedPtr
Definition: untypedSharedPtr.h:128
const std::type_info & getType() const override
Polymorphic getType() function.
Definition: untypedSharedPtr.h:116