cartobase  5.0.5
carto::Object Class Reference

#include <cartobase/object/object.h>

Inheritance diagram for carto::Object:
Collaboration diagram for carto::Object:

Public Member Functions

 Object ()
 Object (const Object &)
 Object (GenericObject *data, bool externalowner=false)
virtual ~Object ()
Objectoperator= (const Object &)
 uses the reference-counting so the underlying GenericObject is shared More...
bool isSameObject (const Object &) const
 compares the addresses of the underlying GenericObjects More...
bool isNone () const
 check if we hold a "none" object. More...
bool operator== (const Object &other) const
bool operator!= (const Object &other) const
Object value (const Object &value)
- Public Member Functions inherited from carto::rc_ptr< GenericObject >
 rc_ptr ()
 rc_ptr (GenericObject *p)
 rc_ptr (GenericObject *p, bool externalowner)
 rc_ptr (std::auto_ptr< U > r)
void reset (GenericObject *p=NULL)
GenericObjectget () const
bool operator< (const rc_ptr< GenericObject > &other) const
 operator insipid * () const
- Public Member Functions inherited from carto::ref< GenericObject >
 ref ()
 ref (GenericObject *pObject)
 ref (GenericObject *pObject, bool externalowner)
 ref (std::auto_ptr< U > r)
 ref (const ref< GenericObject > &other)
 ref (const ref< R > &other)
 ~ref ()
GenericObjectrelease ()
ref< GenericObject > & operator= (const ref< GenericObject > &other)
GenericObjectoperator-> () const
GenericObjectoperator* () const
GenericObjectpointer () const
- Public Member Functions inherited from carto::const_ref< GenericObject >
 const_ref ()
 const_ref (const GenericObject *pObject)
 const_ref (const GenericObject *pObject, bool externalowner)
 const_ref (std::auto_ptr< U > r)
 const_ref (const ref< GenericObject > &other)
 const_ref (const const_ref< GenericObject > &other)
 const_ref (const ref< R > &o)
 const_ref (const const_ref< R > &other)
 ~const_ref ()
const_ref< GenericObject > & operator= (const ref< GenericObject > &other)
const_ref< GenericObject > & operator= (const const_ref< GenericObject > &other)
bool isNull () const
bool operator== (const ref< GenericObject > &other) const
bool operator== (const GenericObject *pointer) const
bool operator== (const const_ref< GenericObject > &other) const
bool operator!= (const ref< GenericObject > &other) const
bool operator!= (const const_ref< GenericObject > &other) const
bool operator!= (const GenericObject *pointer) const
const GenericObjectoperator-> () const
const GenericObjectoperator* () const
const GenericObjectpointer () const
int refCount () const
- Public Member Functions inherited from carto::RefData< GenericObject >
int count () const

Static Public Member Functions

template<typename T >
static Object value ()
 factory function: builds an Object by using the default constructor More...
template<typename T >
static Object value (const T &)
 factory function: builds an Object by copying the value into a ValueObject storage wrapper More...
template<typename T >
static Object reference (T &value)
 factory function: builds an Object by referencing the value from a ReferenceObject storage wrapper. More...
template<typename T >
static Object reference (const T &value)
 This method remove "constness" of it argument and call its non const equivalent. More...

Additional Inherited Members

- Public Types inherited from carto::ref< GenericObject >
typedef GenericObject referenced_type
- Public Types inherited from carto::const_ref< GenericObject >
typedef GenericObject referenced_type

Detailed Description

Basically, an Object is used whenever it is necessary to use data which type is not known at compile time. Therefore, an Object instance can contain any type of data and it can change at run time. However, C++ is a strongly typed language, it is therefore impossible to handle untyped data. To be able to define a typed generic API for untyped objects, we choosed to base our API on a limited (but extensible) set of atoms and aggregates. Atoms are objects that cannot be split into smaller objects. Aggregates are structures composed of objects (which are either atoms or aggregates).

The basic Object API uses the following standard atoms:

  • Scalar: represents any numeric value
  • String: a characters string (like the C++ standard library class std::string)

Atoms can be grouped and/or organised with the following standard aggregates:

  • Array: an ordered series of objects. The number of objects in the array as well as the type of each element can vary at run time.
  • Dictionary: a kind of untyped C/C++ structure. A Dictionary is composed of a series of (key, value) pairs where key is a String and value is an object.

All these atoms and aggregates (i.e. all objects) can be accessed through a set of C++ classes inheriting from Interface and described below.

Why using Object ?

There are two main reasons that led us to build generic object API. The first one is the need to have untyped dynamic array and dictionaries. This structures are required to store data from the generic minf format. This format contains a Dictionary which content is read from a file at run time. The main idea is to allow the storage of any kind of value in a minf file. The second reason is related to the need to exchange complex data and algorithm between C++ programs and other language (mainly Python. It can be thought as a generalization of the minf requirement. The minf format can be considered as an external (i.e. non C++) language. Therefore, if the tools defined to wrap C++ objects to minf format are generic enough, they can be used to wrap these objects to other languages. Now, the Interface API is generic and language independant, therefore it is being used to create wrappers between C++ and various languages (at least minf-python, minf-XML and Python).

Object's interfaces

The main class that is going to be declared by generic objects users is Object. This class behaves like a pointer to a virtual class called GenericObject. Most people will not have to bother about GenericObject. The only point to remember is just that since Object is pointer alike, almost all of its methods are accessed through the "arrow" syntax (e.g. object->method()) instead of the "dot" syntax (e.g. object.method()).

Object's methods are grouped by interface. Each interface correspond to a set of methods implementing access to a specific atom or aggregate. Interfaces are pure virtual classes derived from Interface. There is a set of standard interfaces which define the API for standard atoms and standard aggregate. It is also possible to define new custom interfaces as explained below.

The standard interface methods differ from custom interface methods. Indeed, standard interfaces are defined before generic objects but custom interfaces are not known when generic objects are defined. Therefore, only standard interfaces methods can be accessed directly from Object's instance (via inheritance). Access to custom interface is described below.

Standard interfaces

Here is a summary of the standard interfaces. Report to each interface documentation for more information:

How to create an Object ?

Object behave much like a generic pointer to a real C++ value. Unlike pointers, Object instances can manage memory usage and do all necessary memory allocation/deallocation. In this case the C++ value "belongs" to the Object. Such objects are called value objects. On the other hand, it is sometimes necessary to reference an existing C++ value as a generic object without memory management. Such objects are called reference objects.

There are two functions to create either a value object or a reference. Object::value() returns an Object containing a copy of the value given in parameter whereas Object::reference() returns an object pointing to the object given in parameter. The real type of the object is the type of the parameter (these functions are template).


// This will build a ref-counted copy of the object
Object rc1 = Object::value( (int) 12 );

But if you want to reference an existing object:

int existing = 12; // this one should not be destroyed before rc2
Object rc2 = Object::reference( existing );

How to use Objects ?

There are two ways to read or modify the value of an object. If you know the real type of the object, you can access to the stored via the value() and setValue() functions. These functions only work if you try to access the correct data type (exact type match: no inheritance is taken into account), otherwise the functions throw an exception. On the other hand, if you do not know the real object type, you must use either the standard interface or the custom interface API.

How to use Object's standard interfaces

To do...

Object API uses an Interface system: subclasses of Interface implement some "standard" APIs that can be accessed via the GenericObject::getInterface function. All GenericObjects inherit the most common interfaces: ScalarInterface, StringInterface, DictionaryInterface, DynArrayInterface, DictionaryIteratorInterface, and others implied by those listed here.

A specialized GenericObject which stores (or references) an object that implements a specific Interface will allow to get and use this interface: getInterface() will return a pointer to the stored object matching interface. If the stored object itself does not implement the interface, getInterface() will return a null pointer.

Some Interface may be implemented by the specialized GenericObject, not by the stored object. For instance DictionaryInterface is implemented on map<string, Object> GenericObject specializations even if map doesn't implement it directly.

How to use Object's custom interfaces

To do...


using namespace std;
using namespace carto;
// store an int and a string into a STL vector
Object obj = Object::value( vector<Object>() );
obj->insertArrayItem( -1, Object::value( int( 10 ) ) );
obj->insertArrayItem( -1, Object::value( string( "yup" ) ) );
// access elements;
cout << "int : " << obj->getArrayItem(0)->value<int>() << endl; // int
cout << "string: " << obj->getArrayItem(1)->value<string>() << endl; // string
// The above code is equivalent to this one, not using Object pointers:
vector<Object> vec;
vec.push_back( Object::value( int( 10 ) ) );
vec.push_back( Object::value( string( "yup" ) ) );
// access elements;
cout << "int : " << vec[0]->value<int>() << endl; // int
cout << "string: " << vec[1]->value<string>() << endl; // string
// to change an already stored value, you can either copy the
// whole ref counter (detaches it from other references to the older
// values)
vec[0] = Object::value( int( 24 ) );
// in this case you can also change type
vec[0] = Object::value( string( "I'm a string now" ) );
// but if you want to share references and keep the same data type,
// it's more efficient to only change the referenced value:
vec[0]->value<int>() = 32;

Input / Output

Generic objects can be read from and written to disk in two formats:

  • minf-XML: a XML format
  • minf-python: a python-like format

see PythonReader, PythonWriter, readMinfXML.

See also

Definition at line 605 of file object.h.

Constructor & Destructor Documentation

◆ Object() [1/3]

carto::Object::Object ( )

Definition at line 1405 of file object.h.

Referenced by operator==(), reference(), and value().

◆ Object() [2/3]

carto::Object::Object ( const Object x)

Definition at line 1410 of file object.h.

◆ Object() [3/3]

carto::Object::Object ( GenericObject data,
bool  externalowner = false 

Definition at line 1415 of file object.h.

◆ ~Object()

carto::Object::~Object ( )

Definition at line 1421 of file object.h.

Member Function Documentation

◆ isNone()

bool carto::Object::isNone ( ) const

check if we hold a "none" object.

At the moment, a "none" object is null: the reference counter holds a null pointer, so you must check it before accessing any GenericObject method via the operator->() . In the future, we may define a None type which will not be a null pointer, allowing the use of GenericObject methods, which will throw exceptions rather than crash the program.

Note that a singleton None object is defined as a global variable: carto::none()

Definition at line 1548 of file object.h.

◆ isSameObject()

bool carto::Object::isSameObject ( const Object ) const

compares the addresses of the underlying GenericObjects

◆ operator!=()

bool carto::Object::operator!= ( const Object other) const

◆ operator=()

Object & carto::Object::operator= ( const Object other)

uses the reference-counting so the underlying GenericObject is shared

Definition at line 1427 of file object.h.

◆ operator==()

bool carto::Object::operator== ( const Object other) const

Definition at line 1438 of file object.h.

References carto::rc_ptr< T >::get(), Object(), and value().

◆ reference() [1/2]

template<typename T >
Object carto::Object::reference ( T &  value)

factory function: builds an Object by referencing the value from a ReferenceObject storage wrapper.

The original value object must not be destroyed while the new object is still in use.

Definition at line 1532 of file object.h.

References Object().

Referenced by carto::PropertySet::addBuiltinProperty(), carto::ReferenceObject< T >::clone(), carto::getObjectHeader(), reference(), carto::PropertySet::setProperty(), and value().

◆ reference() [2/2]

template<typename T >
Object carto::Object::reference ( const T &  value)

This method remove "constness" of it argument and call its non const equivalent.

Definition at line 1541 of file object.h.

References reference().

◆ value() [1/3]

template<typename T >
Object carto::Object::value ( )

◆ value() [2/3]

template<typename T >
Object carto::Object::value ( const T &  v)

factory function: builds an Object by copying the value into a ValueObject storage wrapper

Definition at line 1491 of file object.h.

References Object().

◆ value() [3/3]

Object carto::Object::value ( const Object value)

Definition at line 1500 of file object.h.

References Object(), reference(), and value().

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