DynObj: Wrap a DAO with strict ownership
You need a class that holds a pointer to a dynamically allocated object (i.e. one that was created via new and must be destroyed via delete) and represents the DAO as much as possible where the DAO is used, and enforces strict ownership, i.e.:
- No more than one DynObj can have the DAO;
- Automatically delete the DAO when the DynObj is destroyed.
Moreover,
- No implicit copy (since that would require shared ownership, which contradicts the above, or move-on-copy semantics, which is undesirable for reasons discussed extensively, cf. for instance how std::auto_ptr can't be used inside STL containers);
- No deep copy of the DAO, since DAO's have non-trival copy requirements (e.g. polymorphic DAO's require virtual copy method, etc);
The DynObj offers type safety, hence templates are required (inheritence doesn't work because the DAO is only held known by pointer and is not created on the stack but on the heap).
Thus is born the DynObj<T> class.
DynTmp: Return a DAO from a function
With pointers, you would do the following: Foo* getFoo() {
Foo* foo = new Foo;
return foo;
}
This is fraught with error because if the return value from getFoo() is not captured, you get at least a memory (and possibly even a resource) leak.
With DynObj you would want to do, but can't, the following:
DynObj<Foo> getFoo() {
DynObj<Foo> foo( new Foo );
return foo;
}
This is not possible because it would require implicit move semantics, which, as seen in the previous usage case, is not supported.
It seems that a special proxy is needed to represent unnamed temporaries like the return value of getFoo(). The role of this proxy should be purely to transfer a DAO from somewhere to a receiving DynObj, in a clear and unmistakable fashion, or if there is no DynObj to recieve it, to delete it. I.e.,
DynTmp<Foo> getFoo() {
DynObj<Foo> foo( new Foo );
return foo.moveToTmp();
}
Thus is born the DynTmp<T> class to represent unnamed temporaries. The moveToTmp() is the "clear and unmistakable fashion". DynTmp also allows
DynTmp<Foo> getFoo() { return new Foo; }
...
DynObj<Foo> dynObj = getFoo();
which is safe even if the return value of getFoo() is not used. As explained in the Use of DynObj in value-based containers section, another example of use of DynTmp is std::list<DynObj<Foo>::InValueContainer> list;
list.push_back(DynTmp<Foo>(new Foo));
Note that DynTmp implements move-on-copy semantics.
DynTmp<T> createT() {return new T;}
DynObj<T> dynObj = createT();
RRef: Automate verification of DAO on access
Ownership of a DAO is often an implementation detail, from the point of view of other functions/class that simply access the DAO (i.e., those that access it don't care who owns it or even if it is owned). Passing around the DAO could easily be done by get a pointer to the DAO from the DynObj. Often, you need to store such pointer for later use. However, verifying that the DAO still exists when it is accessed is not possible without some assistance from the library.
Therefore, provide a class that represents a reference to the DAO, and automatically asserts that the DAO still exists, whenever the DAO is accessed.
Thus is born the RRef<T> class. This class simply stores the pointer to the DAO, given to it by a DynObj, and does an assert before the DAO is accessed through one of RRef's member functions:
DynObj<Foo> foo;
foo().method();
RRef<Foo> refFoo;
refFoo().method();
The method of checking that a DAO exists is an implementation detail and is not discussed here.
RRefable: allow automatic variable to be RRef'd
Conceptually, RRef doesn't care that the pointer it holds is a DAO, just that it has some way of knowing whether that pointer is still pointing to something valid. It is quite plausible that an object created on the stack, i.e. an automatic variable, could have a pointer to it given to another object for later access. For instance, an observer would give a pointer to itself to an observable so the observable can notify the observer when a state change has occurred in the observable.
It would therefore be useful if it would be very simple to make a class usable as an RRef. Even better, if this automatically makes all subclasses also RRef'able. Inheritance is ideal:
class Bar: public RRefable {...};
...
Bar bar;
bar.method();
RRef<Bar> refbar(bar);
refbar().method();
The method of checking that a RRefable exists is an implementation detail and is not discussed here.
Next usage pages:
Generated on Mon Aug 4 18:51:32 2003 for NoPtr C++ Library by
1.3.2