This is taken partially from the doxygen documentation (already in progress) and should
better tell more about the Library itself than to tell how to use it.
I will change this in the next time and move this page downwards to a new sub page.
The library contains a C++ class that can be used instead of any other type of
variant classes or structures.
It is easy-to-use and provides a lot of features such as:
at()and count()std::shared_ptr and does not copy values but rather add references to objectsTo build the library you will need at least MSVC 10 or better (express version should do).
Other compilers may work, but I didn't test them yet.
If you make the library compile with another compiler, please let me know, drop me a line
and/or send me the makefile together with version of you compiler and system :)
The library consist mainly of the main data item class dtitem, that is the data item class itself.
All classes, functions and variables are located in namespace dt.
All strings in the library are of type dt::str_type.
This is a typedef to std::string currently but may be changed to e.g. std::wstring later.
dt::dtitemDoRef is s a specialized dt::RefPtr<std::shared_ptr> and is the type to be used with
the library.
A DoRef may point to nothing or to created dtitem. To call a method of the item simply use the ->
e.g.
~~~~ (cpp)
DoRef ref;
ref.reset(new dt::dtitem("struct")); // creates the object, ref holds the reference to it
// calls method name() which is 'struct' for this item
std::cout << ref->name() << std::endl;
// ==> >struct
`DoRef` objects may be used to assign another `dtitem` object or can be added to a child list of a `dtitem`
without any concerns about freeing up something. This is done by `DoRef` automatically.
## Samples
Here are some sample C++ sources, just for given a first impression about the functions.
Refer for details to the complete doxygen documentation as provided.
### DoRef and exception handling
Whenever dealing with `DoRef` (or `dtitem`) classes you should consider to
handle `std::exception` throwings.
~~~~ (cpp)
void test()
{
DoRef r;
// this line will throw a dt::ex_unreferenced() exception rather
// than an access violation what would be the result when using
// shared_ptr and not DoRef classes
std::cout << r->name() << std::endl;
}
A better handling would be:
~~~~ (cpp)
void test()
{
DoRef r;
try {
// this line will throw a dt::ex_unreferenced() exception
std::cout << r->name() << std::endl;
}
catch (const std::exception& ex)
{
std::cerr << "exception caught: " << ex.what() << std::endl;
}
}
---------
### Creating a DoRef object
Creating an object is safe when you create it "embedded" in a `DoRef` like:
~~~~ (cpp)
void test()
{
DoRef r;
// the created object is "embedded" into the r object and
// destroyed when r is going out-of-scope
//i.e. leaving the test() function.
r = new dt::dtstruct("hello world");
std::cout << "created a struct with name = "
<< r->name() << std::endl;
// r will destruct the child object automatically
}
If you want to destruct a DoRef explicitely, you can remove it from a
parent object's child list by:
~~~~ (cpp)
void test()
{
DoRef r;
// create the parent object
r = new dt::dtstruct("hello");
{ // extra scope for adding a new item
// create a new string type dtitem and add it to 'r'
DoRef childRef(new dtstring("world"));
r->add(childRef);
}
std::cout << "'r' contains count = child object(s)"
<< r.count() << ")" << std::endl; // > 1
{ // extra scope for the removal test
// get a pointer to the first child object of 'r'
DoRef childRef = r->at(0);
// remove it from the child list of 'r'
r->remove(childRef);
// the referenced object of childRef is destroyed here
}
std::cout << "'r' contains count = child object(s)"
<< r.count() << ")" << std::endl; // > 0
}
-------
### DoRef and parent()
Use the relation `child->parent` safely.
The design of the `dtitem` child list is done by using `DoRef` classes to
reference objects.
An object contains a reference to its parent as well.
This is a so called `weak` kind of reference or simply said its just a pointer to a `dtitem`.
This circumvents recursion trouble that otherwise would appear when adding an
object to a parent and the object would reference it with a `DoRef` instead.
I.e. you may "access" the parent of a `dtitem` object only with a raw `const dtitem*`
and never using a `DoRef`.
You must also expect to get a null pointer when doing so.
~~~~ (cpp)
void test(DoRef r)
{
DoRef guardRef(r); // do not allow destruction from outside e.g. another thread
if (r.empty()) {
std::cerr << "'r' does not point to a valid object" << std::endl;
return;
}
if (r->empty()) {
std::cout << "Given 'r' does not contain any child object" << std::endl;
return;
}
// get a pointer to the first child object of 'r'
DoRef childRef = r->at(0);
// DoRef parentRef = childRef->parent();
// WRONG: This would create a NEW shared_ptr with pointing to
// the object childRef->parent() points to
//
// And this would destruct the new shared_ptr when leaving
// the inner scope.
//
// What finally would lead to an access violation when leaving
// test() or the function called test()
// Correctly accessing the parent by using:
const dtitem *parentPtr = childRef->parent();
// the reference count of childRef's parent is not changed
if (parentPtr) {
std::cout << "The parent object's name = "
<< parentPtr->name() << std::endl;
}
}