In particular, a developer writing code using Clipper objects should be able to do so with minimal or no use of pointers, or of the built-in new
and delete
operators. References are used in preference to pointers where possible. Heap objects, with the corresponding dangers of memory leakage, are avoided. (However, for the cases where the developer needs to use heap objects, an optional mechanism is provided for automatic garbage collection).
Clipper objects should generally be passed by reference rather than by value.
float
or double
for the representation of floating-point numbers. This is acheived by defining floating-point values with a user-defined type ftype
. This is set by a typedef
in lib/clipper_util.h.Data may have a different type. Since data objects may be large, these may be individually typed to save memory or provide additional precision as required. Data types are based on templates in lib/clipper_datatypes.h.
The type for Fast-Fourier transforms is dependent on the FFTw library to which Clipper is linked. FFTw may be compiled for float
or double
.
Since crystallographic FFTs generally have quite short dimensions (< 1000), float
is recommended.
Clipper
namespace, and can be accessed by using the Clipper:
: prefix or using namespace Clipper;
Templates for reciprocal space datatypes are provided in the Clipper::datatypes
namespace. Instantiations of these types for float
and double
data are provided in Clipper::data32
and Clipper::data64
.
Classes are all named with an initial capital letter. Method names are all lowercase, with words separated by underscore ('_'). A handful of top level functions are implemented; these have an initial capital letter to distinguish them from standard library functions.
Sometimes it may be useful to create Clipper container objects on the heap. In this case, the developer can arrange for the object to be destroyed when it is no-longer needed. However an alternative, automatic, method for memory management is provided, in the form of a destroyed_with_parent
flag. If in object is created on the heap (i.e. with new
), this flag may be set as follows:
Container* new_container = new Container( parent, "A container" ); new_container->set_destroyed_with_parent();
Then, as soon as parent
is destroyed, either by going out of scope, or by a delete
operator, the new container will also be destroyed.
Passing or assigning an object always results in a 'deep copy', i.e. all of the data associated with the object is copied.
There are a few places where I haven't yet finished implementing all of these standards, but I'm working on it.