Newer
Older
#pragma once
#include <alib/variant>
#include <object/AnyObject.h>
class Object {
/**
* The wrapped data.
*/
ext::cow_shared_ptr < AnyObjectBase > m_data;
/**
* \brief
* Unifies the shared pointers. For internal use when two pointer eval equal.
*/
void unify ( Object & other ) {
if ( this->m_data.use_count ( ) > other.m_data.use_count ( ) )
other.m_data = this->m_data;
else
this->m_data = other.m_data;
}
/**
* \brief
* Helper method to detect variant content and call make method on the object from inside of the variant.
*/
static Object processVariant ( Variant && data ) {
auto visitor = [] ( auto && element ) {
return Object ( std::forward < decltype ( element ) > ( element ) );
};
return ext::visit ( visitor, std::forward < Variant > ( data ) );
/**
* Constructor that wraps raw pointer. Takes ownership of the pointer.
*/
explicit Object ( AnyObjectBase * data ) : m_data ( data ) {
}
/**
* Sets the wrapped object from raw pointer. Takes ownership of the pointer.
*
* Internally handles situation like storing the same value that is already wrapped. Usefull in normalisation.
*/
void setData ( AnyObjectBase * data ) {
if ( & getData ( ) == data )
return;
this->m_data = ext::cow_shared_ptr < AnyObjectBase > ( data );
}
public:
/**
* \brief
* Specialisation of the make method for c-strings.
*/
explicit Object ( const char * string ) : Object ( std::string ( string ) ) {
}
/**
* \brief
* Specialisation of the make method for objects that are not from the object hierarchy of Algorithms library
*/
template < class Type, typename Enable = std::enable_if < ! std::is_same_v < std::decay_t < Type >, Object >, void > >
explicit Object ( Type && data ) : Object ( object::AnyObject < typename std::decay < Type >::type > ( std::forward < Type > ( data ) ) ) {
}
/**
* \brief
* Specialisation of the make method for variants.
*
* \details
* The resulting object is not constructed from the variant itself but from the value stored inside. If the value stored inside the variant is variant again, the process is repeated.
*/
template < class ... Types >
explicit Object ( ext::variant < Types ... > && data ) : Object ( processVariant ( std::move ( data ) ) ) {
}
/**
* \brief
* Specialisation of the make method for variants.
*
* \details
* The resulting object is not constructed from the variant itself but from the value stored inside. If the value stored inside the variant is variant again, the process is repeated.
*/
template < class ... Types >
explicit Object ( const ext::variant < Types ... > & data ) : Object ( processVariant ( data ) ) {
* Constructor that wraps an object given by a constant reference. Uses clone of the parameter internally.
template < class Type >
explicit Object ( const AnyObject < Type > & data ) : m_data ( data.clone ( ) ) {
* Constructor that wraps an object given by a reference. Uses clone of the parameter internally.
*/
template < class Type >
explicit Object ( AnyObject < Type > & data ) : m_data ( data.clone ( ) ) {
}
/**
* Constructor that wraps an object given by an r-value reference. Uses clone of the parameter internally.
template < class Type >
explicit Object ( AnyObject < Type > && data ) : m_data ( std::move ( data ).clone ( ) ) {
* Constructor that wraps an object given by constant reference. Uses clone of the parameter internally.
explicit Object ( const AnyObject < object::Object > & data ) : Object ( data.getData ( ) ) {
}
/**
* Constructor that wraps an object given by r-value reference. Uses clone of the parameter internally.
*/
explicit Object ( AnyObject < object::Object > && data ) : Object ( std::move ( data ).getData ( ) ) {
}
/**
* Gets the wrapped object.
*
* \returns wrapped object.
*/
const AnyObjectBase & getData ( ) const {
AnyObjectBase & getData ( ) {
return * m_data;
}
/**
* Sets the wrapped object from constant reference. Uses clone of the parameter internally.
*/
void setData ( const AnyObjectBase & data ) {
setData ( data.clone ( ) );
}
/**
* Sets the wrapped object from r-value reference. Uses clone of the parameter internally.
*/
void setData ( AnyObjectBase && data ) {
setData ( std::move ( data ).clone ( ) );
}
/**
* The three way comparison implementation
* \param other the other object to compare with.
* \returns the strong ordering between this object and the @p other.
std::strong_ordering operator <=> ( const Object & other ) const {
if ( this->m_data.get ( ) == other.m_data.get ( ) )
return std::strong_ordering::equal;
std::strong_ordering res = ( * this->m_data ) <=> ( * other.m_data );
if ( res == 0 )
const_cast < Object * > ( this )->unify ( const_cast < Object & > ( other ) );
* The equality comparison implementation.
* \param other the other object to compare with.
*
* \returns true if this and other objects are equal, false othervise
*/
bool operator ==( const Object & other ) const {
if ( this->m_data.get ( ) == other.m_data.get ( ) )
return true;
bool res = ( * this->m_data ) == ( * other.m_data );
if ( res )
const_cast < Object * > ( this )->unify ( const_cast < Object & > ( other ) );
return res;
}
/**
* Print the wrapped object as raw representation to ostream.
*
* \param os ostream where to print
* \param instance wrapper to print
*
* \returns modified output stream
*/
friend std::ostream & operator <<( std::ostream & os, const Object & instance ) {
return os;
}
/**
* Casts the wrapped object to as compact as possible string representation.
*
* \returns string representation of the wrapped object
*/
explicit operator std::string ( ) const {
return m_data->operator std::string ( );
* \brief
* Increments the unique counter of the object by one. Prefix version.
this->getData ( ).increment ( 1 );
return *this;
}
/**
* \brief
* Increments the unique counter of the object by one. Postfix version.
*
* \return this instance
*/
Object operator ++ ( int ) {
Object res = * this;
++ * this;
return res;
}
/**
* \brief
* Increments the unique counter of the object.
*
* \param by how much to increment
*/
Object operator += ( unsigned by ) {
this->getData ( ).increment ( by );
/**
* Getter of unique identifier
*
* \return the unique identifier
*/
unsigned getId ( ) const {
return this->getData ( ).getId ( );
}