Simbody
3.5
|
This class provides some infrastructure useful in making SimTK Private Implementation (PIMPL) classes. More...
Public Types | |
typedef PIMPLHandle< HANDLE, IMPL, PTR > | HandleBase |
typedef HandleBase | ParentHandle |
Public Member Functions | |
bool | isEmptyHandle () const |
Returns true if this handle is empty, that is, does not refer to any implementation object. More... | |
bool | isOwnerHandle () const |
Returns true if this handle is the owner of the implementation object to which it refers. More... | |
bool | isSameHandle (const HANDLE &other) const |
Determine whether the supplied handle is the same object as "this" PIMPLHandle. More... | |
void | disown (HANDLE &newOwner) |
Give up ownership of the implementation to an empty handle. More... | |
PIMPLHandle & | referenceAssign (const HANDLE &source) |
"Copy" assignment but with shallow (pointer) semantics. More... | |
PIMPLHandle & | copyAssign (const HANDLE &source) |
This is real copy assignment, with ordinary C++ object ("value") semantics. More... | |
void | clearHandle () |
Make this an empty handle, deleting the implementation object if this handle is the owner of it. More... | |
const IMPL & | getImpl () const |
Get a const reference to the implementation associated with this Handle. More... | |
IMPL & | updImpl () |
Get a writable reference to the implementation associated with this Handle. More... | |
int | getImplHandleCount () const |
Return the number of handles the implementation believes are referencing it. More... | |
Protected Member Functions | |
PIMPLHandle () | |
The default constructor makes this an empty handle. More... | |
PIMPLHandle (IMPL *p) | |
This provides consruction of a handle referencing an existing implementation object. More... | |
~PIMPLHandle () | |
Note that the destructor is non-virtual. More... | |
PIMPLHandle (const PIMPLHandle &source) | |
The copy constructor makes either a deep (value) or shallow (reference) copy of the supplied source PIMPL object, based on whether this is a "pointer
semantics" (PTR=true) or "object (value) semantics" (PTR=false, default) class. More... | |
PIMPLHandle & | operator= (const PIMPLHandle &source) |
Copy assignment makes the current handle either a deep (value) or shallow (reference) copy of the supplied source PIMPL object, based on whether this is a "pointer sematics" (PTR=true) or "object (value) semantics" (PTR=false, default) class. More... | |
void | setImpl (IMPL *p) |
Set the implementation for this empty handle. More... | |
bool | hasSameImplementation (const HANDLE &other) const |
Determine whether the supplied handle is a reference to the same implementation object as is referenced by "this" PIMPLHandle. More... | |
This class provides some infrastructure useful in making SimTK Private Implementation (PIMPL) classes.
These consist of a "handle" class and an "implementation" class. The handle contains only a single pointer, which points to the implementation class whose definition is unknown to the SimTK client. The implementation class has a pointer back to *one* of the handles that points to it – that one is called the "owner handle" and is the only one which will delete the implementation object when the handle is deleted or goes out of scope. All other handles are merely references to the implementation object, and must not be used after the owner handle is deleted.
The methods defined below require a definition for the implementation class, so can't be instantiated on the client side. Instead they are instantiated on the library side when needed in the implementation of the PIMPL handle class derived from the PIMPLHandle base.
By the time of instantiation, we must have a definition for the IMPL class supplied to the templatized base class. We expect that the IMPL class will be derived from PIMPLImplementation declared below. We also expect to find certain methods defined, with these names and meanings:
IMPL* IMPL::clone() const This creates an implementation object identical to the one we have, except that its owner handle is set to null. We expect the owner handle to be filled in by the derived Handle class, which should have initiated the PIMPLHandle operation which had the need to clone().
const HANDLE& IMPL::getOwnerHandle() const If the IMPL object does not have an owner, this is expected to assert(); that would indicate that the derived Handle class did not properly register itself as the owner upon construction. Otherwise, this routine returns a reference to the *derived* Handle class, NOT to the PIMPLHandle parent class! We expect, however that the Handle class was derived from this PIMPLHandle so that we can static_cast up here and then compare with 'this'.
Usage: class MySecretImpl; class MyHandle : public PIMPLHandle<MyHandle,MySecretImpl>
There is an optional third template argument, a bool, which can be set true if you want the handle to have pointer semantics rather than the usual object ("value") semantics. Pointer semantics objects have shallow copy constuctor and copy assignment implementations so that they are normally references to objects rather than owners, and pointer semantics owner handles can't be the target of an assignment.
typedef PIMPLHandle<HANDLE, IMPL, PTR> SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::HandleBase |
typedef HandleBase SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::ParentHandle |
|
inlineprotected |
The default constructor makes this an empty handle.
|
explicitprotected |
This provides consruction of a handle referencing an existing implementation object.
If the supplied pointer is null the result is the same as the default constructor.
|
protected |
Note that the destructor is non-virtual.
This is a concrete class and so should be all the handle classes derived from it. If this handle is the owner of its implementation, the destructor will destroy the implementation object as well. Any other handles referencing the same implementation will then be invalid, although there will be automated detection of that. Be very careful to ensure that owner handles always outlive their reference handles.
|
protected |
The copy constructor makes either a deep (value) or shallow (reference) copy of the supplied source PIMPL object, based on whether this is a "pointer semantics" (PTR=true) or "object (value) semantics" (PTR=false, default) class.
|
inline |
Returns true if this handle is empty, that is, does not refer to any implementation object.
bool SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::isOwnerHandle | ( | ) | const |
Returns true if this handle is the owner of the implementation object to which it refers.
An empty handle is not considered by this method to be an owner. You can check for an empty handle using isEmptyHandle().
bool SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::isSameHandle | ( | const HANDLE & | other | ) | const |
Determine whether the supplied handle is the same object as "this" PIMPLHandle.
void SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::disown | ( | HANDLE & | newOwner | ) |
Give up ownership of the implementation to an empty handle.
The current handle retains a reference to the implementation but is no longer its owner. This method requires the current handle to be an owner, and the supplied handle to be empty.
PIMPLHandle< HANDLE, IMPL, PTR > & SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::referenceAssign | ( | const HANDLE & | source | ) |
"Copy" assignment but with shallow (pointer) semantics.
As long as this is not an owner handle already, make it reference the source implementation. It is not allowed for an owner handle to be the target of a reference assignment; clear the handle explicitly first with clearHandle() if you want to do that. This is the default copy and assignment behavior for pointer semantics handle classes (that is, those which set the PTR template argument to true). Caution: although the PIMPLHandle is taken const here, we obtain a writable pointer to the implementation, meaning that it can be modified through the reference handle if that handle is non-const.
PIMPLHandle< HANDLE, IMPL, PTR > & SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::copyAssign | ( | const HANDLE & | source | ) |
This is real copy assignment, with ordinary C++ object ("value") semantics.
Deletes the current implementation if owned; then replaces with a new copy of the source implementation, of which this handle will be the owner. This is the default copy and assignment behavior for normal handle objects, that is, those that let the PTR template argument default or set it to false explicitly. Use referenceAssign() to make a handle refer to an existing implementation rather than creating a new copy.
void SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::clearHandle | ( | ) |
Make this an empty handle, deleting the implementation object if this handle is the owner of it.
A call to isEmptyHandle() will return true after this.
|
inline |
Get a const reference to the implementation associated with this Handle.
This will throw an exception if there is no implementation.
|
inline |
Get a writable reference to the implementation associated with this Handle.
Note that this requires writable access to the handle also. This will throw an exception if there is no implementation.
int SimTK::PIMPLHandle< HANDLE, IMPL, PTR >::getImplHandleCount | ( | ) | const |
Return the number of handles the implementation believes are referencing it.
Throws an exception if there is no implementation. This is for degugging and consistency checking and shouldn't normally be used.
|
protected |
Copy assignment makes the current handle either a deep (value) or shallow (reference) copy of the supplied source PIMPL object, based on whether this is a "pointer sematics" (PTR=true) or "object (value) semantics" (PTR=false, default) class.
In the case of a pointer semantics class, an owner handle can not be the target of an assignment. You can call copyAssign() directly if you want to make a fresh copy of the source, or you can clear this handle first with clearHandle() and then use operator=() or referenceAssign() to turn this handle into a mere reference to the source.
|
protected |
Set the implementation for this empty handle.
This may result in either an owner or reference handle, depending on the owner handle reference stored in the implementation object. This will throw an exception if the handle is already occupied; it cannot be used to replace one implementation with another.
|
protected |
Determine whether the supplied handle is a reference to the same implementation object as is referenced by "this" PIMPLHandle.