GEGELATI
Classes | Public Member Functions | Static Public Member Functions | Public Attributes | List of all members
Data::UntypedSharedPtr Class Reference

Class behaving as a std::shared_ptr whose type is not templated. More...

#include <untypedSharedPtr.h>

Classes

struct  Concept
 Internal structure of the type erasure pattern. More...
 
struct  Model
 Internal templated structure of the type erasure pattern. More...
 

Public Member Functions

 UntypedSharedPtr ()=delete
 Deleted default constructor.
 
template<typename T , class Deleter = std::default_delete<T>>
 UntypedSharedPtr (T *obj, Deleter func=Deleter())
 Main constructor of the UntypedSharedPtr class. More...
 
 UntypedSharedPtr (std::shared_ptr< Concept > concept)
 Constructor from an existing Concept. More...
 
const std::type_info & getType () const
 Accessor to the type of data stored in the UntypedSharedPtr. More...
 
const std::type_info & getPtrType () const
 Accessor to the pointer type of data stored in the UntypedSharedPtr. More...
 
template<typename T >
std::shared_ptr< std::remove_all_extents_t< T > > getSharedPointer () const
 Get the shared_ptr store in the UntypedSharedPtr. More...
 

Static Public Member Functions

template<typename T >
static std::function< void(T *)> emptyDestructor ()
 Get an empty destructor function for any type. More...
 

Public Attributes

std::shared_ptr< const ConceptsharedPtrContainer
 Shared container containing the data structure containing the actual std::shared_ptr.
 

Detailed Description

Class behaving as a std::shared_ptr whose type is not templated.

Instances of this class is that it behaves as a share_ptr, meaning that it contains a pointer to an object that is freed automatically when the last copy of the UntypedSharedPtr associated to this pointer is deleted. The deleter that can be passed as a parameter when building an instance is used to delete the object. By giving an empty function to the constructor, the deletion of the pointer can thus be prevented, and the UntypedSharedPtr can be used to store a regular pointer.

The main difference with the classical std::shared_ptr<T> is that no template parameter specifies what is stored inside the UntypedSharedPtr. Hence, a std:vector<UntypedSharedPtr> can contain shared pointer to any type of data (including primitive types), whereas a std::vector< std::shared_ptr<Base>> can contain only pointers to types derived from a given Base class, which notably prevent such a vector from containing shared pointer to several distinct primitive types.

The code of this class is based on the Type Erasure patterns, and is directly inspired by this example/

Constructor & Destructor Documentation

◆ UntypedSharedPtr() [1/2]

template<typename T , class Deleter = std::default_delete<T>>
Data::UntypedSharedPtr::UntypedSharedPtr ( T *  obj,
Deleter  func = Deleter() 
)
inline

Main constructor of the UntypedSharedPtr class.

Constructs an instance of the UntypedSharedPtr class whose type is given as a template parameter T that is deduced at function call.

For example, the following codes creates an UntypedSharedPtr for an int value:

UntypedSharedPtr ptr{new int(2)}; // Template parameter 'int' deduced
UntypedSharedPtr()=delete
Deleted default constructor.

The default deleter for the given pointer type is used by default, unless a deleter is explicitly given to the constructor. For example, a deleter doing nothing can be given to prevent the shared pointer from deallocating the memory of a variable on the stack.

// Empty Deleter for double pointers.
auto del = [](const double *){};
// Variable on the heap
double a{2.5};
{ // Beginning of a scope
UntypedSharedPtr ptrA{&a, del};
UntypedSharedPtr ptr{new int(2)};
// UntypedSharedPtr ptrA2{&a}; // Problem => deletion of the memory
// will be attempted when leaving
// ptrA2 disappears.
} // End of a scope
// Memory associated to ptr is freed with default deleter for int*
// Memory associated to ptrA is deleted with del, which does
nothing.

As it is the case with std::shared_ptr, when misused, these capacity may result in invalid data access.

Template Parameters
Ttype of the equivalent std::shared_pointer<T>. Beware, const qualifier matters.
Deletertype of the deletion function. Default value is std::default_delete<T>
Parameters
[in]objPointer to the memory managed by the UntypedSharedPtr.
[in]funcThe function used as Deleter when the last copy of the UntypedSharedPtr disappears. Default value is std::default_delete<T>().

◆ UntypedSharedPtr() [2/2]

Data::UntypedSharedPtr::UntypedSharedPtr ( std::shared_ptr< Concept concept)
inline

Constructor from an existing Concept.

This constructor is needed when the pointer type passed to the classical constructor decays automatically into something else. For example, any pointer to a C-style array allocated with 'new T[]' automatically decays to 'T*' when passed to a function. By constructing a Model<W> with the desired template type (eg. W = T[]), it is possible to force the 'getPtr()' method to return this 'T[]' type.

Parameters
[in]conceptthe instance of the Model<T> class for building the UntypedSharedPointer.

Member Function Documentation

◆ emptyDestructor()

template<typename T >
static std::function< void(T *)> Data::UntypedSharedPtr::emptyDestructor ( )
inlinestatic

Get an empty destructor function for any type.

When building an UntypedSharedPtr, this static method can be used to provide an empty destructor for the second argument of the constructor. The template param should be the same as the type of the pointer given to the UntypedSharetPtr constructor.

Template Parameters
Tthe type of the pointer to deallocate.
Returns
the lambda function for deallocating.

◆ getPtrType()

const std::type_info & Data::UntypedSharedPtr::getPtrType ( ) const
inline

Accessor to the pointer type of data stored in the UntypedSharedPtr.

Returns
a const ref to the std::type_info of the pointer type T* of UntypedSharedPtr at construction. Please note that this may differ from the actual type of the data, if this data has a type derived from the base pointer type T. Contrary to the getType method, const qualifiers are preserved with pointer types.
class Base {};
class Derived : public Base {};
// Non const example.
Base * ptrA = new Derived();
UntypedSharedPtr uspA{ptrA}; // shared pointer type is Base.
std::cout << std::uspA.getPtrType().name(); // Prints "Base *"
// Const example
const Base * ptrB = new Derived();
UntypedSharedPtr uspB{ptrA}; // shared pointer type is const Base.
std::cout << std::uspB.getPtrType().name(); // Prints "const Base*"

◆ getSharedPointer()

template<typename T >
std::shared_ptr< std::remove_all_extents_t< T > > Data::UntypedSharedPtr::getSharedPointer ( ) const
inline

Get the shared_ptr store in the UntypedSharedPtr.

This templated function returns the std::shared_ptr hidden in the UntypedSharedPtr. For the function to work, the given template parameter must be the same as the one given during construction of the UntypedSharedPtr. If a Derived class was given at construction, a Base type can not be given to this function. The opposite (Base at construction and Derived to this function) also does not work, even if the actual object associated to the pointer is of type Derived.

If the type given at construction was const, the type given to this function must be const. If the type given at construction was non-const, the type given to this function can either be const or non- const.

class Base {};
class Derived : public Base {};
// Non const example.
Base * ptrA = new Derived();
UntypedSharedPtr uspA{ptrA}; // shared pointer type is Base.
std::shared_ptr<Base> spA1 = uspA.getSharedPtr<Base>(); // OK
std::shared_ptr<const Base> spA2 = uspA.getSharedPtr<const Base>();
// OK
// std::shared_ptr<Derived> spA3 = uspA.getSharedPtr<Derived>(); //
KO
// Const example
const Base * ptrB = new Derived();
UntypedSharedPtr uspB{ptrA}; // shared pointer type is const Base.
//std::shared_ptr<Base> spB1 = uspB.getSharedPtr<Base>(); // KO
std::shared_ptr<const Base> spB2 = uspB.getSharedPtr<const Base>();
// OK
// std::shared_ptr<Derived> spB3 = uspB.getSharedPtr<Derived>(); //
KO
Template Parameters
TType of the retrieved std::shared_ptr<T>.
Returns
the std::shared_ptr<T> of the pointer stored in the UntypedSharedPtr.
Exceptions
std::runtime_exceptionif the template parameter differs from the type given at construction of the UntypedSharedPtr.

◆ getType()

const std::type_info & Data::UntypedSharedPtr::getType ( ) const
inline

Accessor to the type of data stored in the UntypedSharedPtr.

Returns
a const ref to the std::type_info of the template type T of UntypedSharedPtr at construction, or the Model template type for the constructor based on std::shared_ptr<Concept>. Please note that this type may differ from the actual type of the data, if this data has a type derived from the base pointer type T. Also note that any const qualifier will be lost.
class Base {};
class Derived : public Base {};
// Non const example.
Base * ptrA = new Derived();
UntypedSharedPtr uspA{ptrA}; // shared pointer type is Base.
std::cout << std::uspA.getType().name(); // Prints "Base"
// Const example
const Base * ptrB = new Derived();
UntypedSharedPtr uspB{ptrA}; // shared pointer type is const Base.
std::cout << std::uspB.getType().name(); // Prints "Base"

The documentation for this class was generated from the following file: