Workspace 6.21.5
Public Types | Public Member Functions | Related Functions | List of all members
TypedObject< T > Class Template Reference

Template for instantiating a smart pointer to a particular data type. More...

#include <Workspace/DataExecution/DataObjects/typedobject.h>

Inheritance diagram for TypedObject< T >:
[legend]

Public Types

using Factory = DataFactoryTraits< T >
 

Public Member Functions

 TypedObject ()
 
 TypedObject (const T &t)
 
 TypedObject (const TypedObject &obj)
 
 ~TypedObject () override
 
bool canSerialize () const override
 
void clearData () override
 
bool contains (const void *data) const override
 
bool containsData (const DataObject &object) const override
 
void ensureHasData (bool recurse=true) override
 
bool fromQVariant (const QVariant &v) override
 
const ObjectGroupgetAsObjectGroup () const override
 
ObjectGroupgetAsObjectGroup () override
 
T * getData ()
 
const T * getData () const
 
const DataFactorygetFactory () const override
 
bool hasData (bool recurse=true) const override
 
bool load (const SerializedItem &item) override
 
T & operator* ()
 
const T & operator* () const
 
T * operator-> ()
 
const T * operator-> () const
 
TypedObjectoperator= (const TypedObject &src)
 
bool ownsData () const override
 
bool save (SerializedItem &item) const override
 
void setData (T *data, bool ownsData)
 
void setOwnsData (bool b) override
 
void swap (TypedObject &obj)
 
QVariant toQVariant () const override
 
void useData (DataObject &obj, bool transferOwnership=false) override
 
- Public Member Functions inherited from DataObject
template<typename T >
DataObjectadaptTo (bool copy=false)
 
template<typename T >
const DataObjectadaptTo (bool copy=false) const
 
void assign (const DataObject &src)
 
virtual void clearData ()=0
 
DataObjectclone () const
 
bool compareData (const DataObject &other) const
 
bool compareData (const DataObject &other, int &relationship) const
 
virtual bool contains (const void *data) const =0
 
virtual bool containsData (const DataObject &object) const =0
 
void destroy ()
 
virtual void ensureHasData (bool recurse=true)=0
 
virtual bool fromQVariant (const QVariant &v)=0
 
virtual const ObjectGroupgetAsObjectGroup () const =0
 
virtual ObjectGroupgetAsObjectGroup ()=0
 
template<typename T >
T * getData ()
 
template<typename T >
const T * getData () const
 
virtual const DataFactorygetFactory () const =0
 
template<typename T >
T & getRawData ()
 
template<typename T >
const T & getRawData () const
 
virtual TypeAdaptorgetTypeAdaptor (const DataFactory &factory) const
 
virtual bool hasData (bool recurse=true) const =0
 
bool isObjectGroup () const
 
template<typename T >
bool isType () const
 
bool isType (const DataFactory &type) const
 
bool matchesType (const DataObject &otherObject) const
 
virtual bool ownsData () const =0
 
virtual void setOwnsData (bool b)=0
 
bool sharesData (const DataObject &otherObject) const
 
virtual QVariant toQVariant () const =0
 
virtual void useData (DataObject &obj, bool transferOwnership=false)=0
 
bool useDataClone (const DataObject &obj)
 
- Public Member Functions inherited from Serialize
virtual ~Serialize ()=default
 
virtual bool canSerialize () const =0
 
virtual bool load (const SerializedItem &item)=0
 
virtual bool save (SerializedItem &item) const =0
 

Related Functions

(Note that these are not member functions.)

template<typename T >
bool operator!= (const TypedObject< T > &a, const TypedObject< T > &b)
 
template<typename T >
bool operator== (const TypedObject< T > &a, const TypedObject< T > &b)
 
template<typename T >
void swap (TypedObject< T > &a, TypedObject< T > &b)
 

Detailed Description

template<typename T>
class CSIRO::DataExecution::TypedObject< T >

Use this class instead of the type T you wish to use in your workspace application. It provides automated serialization and associates the type with a particular data factory. The use of the data factory ensures correct handling of memory allocation and deallocation across separate compilation modules (eg for data objects passed between shared libraries), as well as safe copying and assignment of data objects.

The TypedObject class template is meant to act mostly like a smart pointer to type T, with one main restriction: you cannot assign a pointer directly to it. Instead, you must let the object be constructed by the data factory. This is handled by the various constructors and the member function ensureHasData(). In rare instances, the setData() function may be more appropriate, but that would generally only be used by internal Workspace code.

A useData() function is provided to force the underlying data to be set to a particular object, but this is not meant for use by ordinary client code. It is used internally to allow the underlying data to be shared between instances of TypedObject, potentially also transferring ownership. The object is not reference counted, but there is a flag to indicate whether the TypedObject owns the data it points to. As long as one instance somewhere owns it, all is good. The Workspace application will generally manage this ownership for you, so you should not attempt to change the ownership state for any object directly.

Most of the time, serialization support for the type T is handled automatically by the workspace. The template implementations provided by the workspace try to determine whether T can be serialized by checking for inheritance from the Serialize class or else the presence of streaming operators. If neither are supplied, serialization is disabled for T automatically.

Member Typedef Documentation

◆ Factory

Constructor & Destructor Documentation

◆ TypedObject() [1/3]

TypedObject ( )
inline

Default constructor which creates an object with no data.

◆ TypedObject() [2/3]

TypedObject ( const TypedObject< T > &  obj)
inline
Parameters
objThe object to copy.

This copy constructor creates a copy of the underlying data held by obj. Regardless of whether obj owns its own data or not, the newly constructed TypedObject will own its own data.

◆ TypedObject() [3/3]

TypedObject ( const T &  t)
inlineexplicit
Parameters
tAn object to copy.

This constructor creates an object whose underlying data will be a copy of t. The TypedObject will own this data.

◆ ~TypedObject()

~TypedObject ( )
inlineoverride

If this object owns its data, then the destructor will delete it.

Member Function Documentation

◆ canSerialize()

bool canSerialize ( ) const
inlineoverridevirtual
Returns
True if this object can be serialized.

For objects that can be serialized, the save and load functions will be used to do the serialization. If this function returns false, both load() and save() must also return false.

Implements Serialize.

◆ clearData()

void clearData ( )
inlineoverridevirtual

Clear the underlying data being held by this object. Clients should not normally need to call this function.

Implements DataObject.

◆ contains()

bool contains ( const void *  data) const
inlineoverridevirtual
Parameters
dataThe data we are comparing the the data objects underyling data.
Returns
True if this object's underlying data matches the address of the specified data. False if the pointers do not match, or the incoming pointer is null.

Implements DataObject.

◆ containsData()

bool containsData ( const DataObject object) const
inlineoverridevirtual
Parameters
objectThe data object we are comparing the data objects underlying data.
Returns
True if this object's underlying data matches the address of the data in the underlying object. False if the pointers do not match, or the incoming pointer is null.

Implements DataObject.

◆ ensureHasData()

void ensureHasData ( bool  recurse = true)
inlineoverridevirtual
Parameters
recurseIf true, ensure not only this object has valid data, but all child objects if this is an object group. The recursion also continues for all subsequent groups below this one too.

Call this function to ensure that we are holding a valid data object. Any new objects created by this call will be owned by the DataObject associated with that particular data (ie that level in the hierarchy).

Implements DataObject.

◆ fromQVariant()

bool fromQVariant ( const QVariant &  v)
inlineoverridevirtual
Parameters
vThe value to store in this data object.

The subclass implementation should take care to handle the case where the data stored in v cannot be converted to the underlying data type. Ideally, the implementation should also consider performance impacts of the conversion and avoid any unnecessary cloning, copy or memory allocation for temporary objects. In most cases, the TypedObject class template will handle these things sensibly, so there should be little need to manually write code for this.

Returns
True if the value could be set, or false otherwise. Note that it is up to the implementation what "success" means, but as a rule of thumb there should be no data loss as a result of calling setValue(toQVariant()).

Implements DataObject.

◆ getAsObjectGroup() [1/2]

const ObjectGroup * getAsObjectGroup ( ) const
inlineoverridevirtual

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Implements DataObject.

◆ getAsObjectGroup() [2/2]

ObjectGroup * getAsObjectGroup ( )
inlineoverridevirtual
Returns
A pointer to the underlying data as an ObjectGroup, or if the underlying data is not derived from ObjectGroup, return a null pointer. Note that if hasData() returns false, then this function will also return a null pointer even if T is derived from ObjectGroup.

Implements DataObject.

◆ getData() [1/2]

T * getData ( )
inline

◆ getData() [2/2]

const T * getData ( ) const
inline

◆ getFactory()

const DataFactory & getFactory ( ) const
inlineoverridevirtual
Returns
The data factory for this object type.

Implements DataObject.

◆ hasData()

bool hasData ( bool  recurse = true) const
inlineoverridevirtual
Parameters
recurseIf true, test not only this object, but all child objects if this is an object group. The recursion also continues for all subsequent groups below this one too.
Returns
True if this object has valid data. If recurse is true, it will only return true if this object and all its descendents have valid data.

Implements DataObject.

◆ load()

bool load ( const SerializedItem item)
inlineoverridevirtual
Parameters
itemSupplies the state to be loaded into this object.

This function will load the state of this object from item. For many object types, this is most easily implemented in terms of the object's input operator (>>).

It would be reasonable for subclass implementations to assume that the data provided in item is in the same form as would have been saved from a call to save.

Returns
If the state of the object could not be loaded, the function returns false. A return value of true implies that the object state was successfully loaded. If canSerialize() returns false, this function must do nothing except return false as well.

Implements Serialize.

◆ operator*() [1/2]

T & operator* ( )
inline

Allows this object to be used like a pointer to the templated type, T.

Returns
A reference to the real data held by this smart pointer.

◆ operator*() [2/2]

const T & operator* ( ) const
inline

Allows this object to be used like a pointer to the templated type, T.

Returns
A const reference to the real data held by this smart pointer.

◆ operator->() [1/2]

T * operator-> ( )
inline

Allows this object to be used like a pointer to the templated type, T.

Returns
A pointer to the real data held by this smart pointer.

◆ operator->() [2/2]

const T * operator-> ( ) const
inline

Allows this object to be used like a pointer to the templated type, T.

Returns
A const pointer to the real data held by this smart pointer.

◆ operator=()

TypedObject & operator= ( const TypedObject< T > &  src)
inline
Parameters
srcThe object to assign from.
Note
The assignment operator should not be used on an object that is sharing its data with another and the other object is for a more derived type than the one being assigned to here. If that happens, memory corruption will occur.

If the type T does not support assignment, the assignment operator makes no modification to the existing object. In such cases, the failure will occur silently, so it is the caller's responsibility to check getFactory().isAssignable() first.

Returns
A reference to this object.

◆ ownsData()

bool ownsData ( ) const
inlineoverridevirtual

The underlying data can be owned by another DataObject, in which case the caller must be very careful to ensure that access to the underlying data is only attempted at times when it can be guaranteed that the owner still exists. When a DataObject is deleted, it will delete its underlying data only if it owns that data. At certain other times, such as during assignment, a DataObject may also delete its underlying data, but again only if it owns that data.

Returns
True if this object owns its data.
See also
setOwnsData(), useData()

Implements DataObject.

◆ save()

bool save ( SerializedItem item) const
inlineoverridevirtual
Parameters
itemWhere to save the state of this object.

This function will serialise the object by saving it to item. For most object types, this is most easily implemented in terms of the object's output operator (<<).

It is allowable for an object to only serialize part of itself. This would be useful if the data it represents has a set of defaults and only those values different to the defaults need to be serialized. Such an implementation then needs to be careful how it handles the complimentary load member function.

Returns
If an object could not be serialised or if the underlying object type does not support serialisation, this function should return false. A return value of true implies that the object was successfully saved to item. If canSerialize() returns false, this function must do nothing except return false as well.

Implements Serialize.

◆ setData()

void setData ( T *  data,
bool  ownsData 
)
inline
Parameters
dataA pointer to the actual data to set this TypedObject to use.
ownsDataIf true, then the data object will own data. See ownsData() for more information.

No copy is made of data regardless of whether ownsData is true or false. In general, this function should be avoided, since it bypasses some of the data factory mechanisms. It is primarily used by the Workspace core code to allow type adaptors to work efficiently.

See also
ownsData(), setOwnsData()

◆ setOwnsData()

void setOwnsData ( bool  b)
inlineoverridevirtual
Parameters
bIf this is true, then the data object will own the underlying data it is currently holding until it either deletes that data, has ownership removed with another call to setOwnsData() or some other action is performed which causes the underlying data to be replaced or cleared.
Note
Client code would not normally call this function. It is used by the workspace internally to manage the transfer of ownership from one data object to another.
See also
ownsData(), useData()

Implements DataObject.

◆ swap()

void swap ( TypedObject< T > &  obj)
inline
Parameters
objObject with which to swap.

This swap function performs a more efficient swap than the default global swap. It merely exchanges the data pointers, taking care to swap ownership states as well.

◆ toQVariant()

QVariant toQVariant ( ) const
inlineoverridevirtual
Returns
This data object converted to a QVariant (it should always be a copy, never the original data, except for when the underlying type is already QVariant).

Implements DataObject.

◆ useData()

void useData ( DataObject obj,
bool  transferOwnership = false 
)
inlineoverridevirtual
Parameters
objThe DataObject whose underlying data is to be shared.
transferOwnershipIf this parameter is true, then ownership will be transferred from obj to this object. Transfer of ownership must be carried out by calling setOwnsData() on obj at the appropriate point. Note that it is an error to set this parameter to true if obj does not own the data when passed into this function.

This function is not often used outside of core workspace code or code related to polymorphic operations. The caller is responsible for ensuring that obj is exactly the same data type as this one (ie no adaptors can be involved). Failure to obey this rule will almost certainly result in crashes.

If you want to make a DataObject hold an existing data item, such as one that you dynamically create and want to pass ownership to the DataObject, you need to use DataFactoryTraits::setData() instead. The rationale for this is that DataFactoryTraits requires a template type to be specified, so its setData() member function will be able to perform checks that the DataObject is of the correct type to hold the data being passed to it.

See also
ownsData(), setOwnsData(), DataFactoryTraits::setData()

Implements DataObject.

Friends And Related Function Documentation

◆ operator!=()

bool operator!= ( const TypedObject< T > &  a,
const TypedObject< T > &  b 
)
related
Parameters
aLeft hand side of inequality check.
bRight hand side of inequality check.
Returns
True if a and b are deemed to be not equal.
See also
operator==(const TypedObject&,const TypedObject&)

◆ operator==()

bool operator== ( const TypedObject< T > &  a,
const TypedObject< T > &  b 
)
related
Parameters
aLeft hand side of equality check.
bRight hand side of equality check.
Returns
True if a and b are deemed to be equal.

Equality is determined based on two objects having the same data. It is considered equal for two objects to both have no data, and unequal if only one has data. If both have data, then the type T's equality operator is used to test the equality of the underlying data. Therefore, equality can only be determined if an equality operator is defined for the type T.

◆ swap()

void swap ( TypedObject< T > &  a,
TypedObject< T > &  b 
)
related
Parameters
aFirst item to swap.
bSecond item to swap.

Swap the two TypedObject instances. This will call the TypedObject::swap member function of a to perform a more efficient swap rather than copying the underlying data.