We are happy to incorporate content from volunteers!!
Coding Patterns
Handling plain tmp fields
\since 1806
A tmp
field is a commonly encountered return container. The tmp
New()
factory method with forwarding makes it more convenient to
handle and avoid repetitve typing. For example,
auto tresult = tmp<vectorField>::New(len, Zero);
auto& result = tresult.ref();
// or alternatively
auto tresult(tmp<vectorField>::New(len, Zero));
auto& result = tresult.ref();
...
return tresult;
- Since the type is already dictated by the template parameter for the
New()
method, anauto
declaration works without issue. When dereferencing, the choice of variable names (result
vstresult
) makes the use clear, and makes the code nicely align.
Anti-pattern: the older style, which is still very evident in much of OpenFOAM, but is much more verbose:
tmp<vectorField> tresult(new vectorField(len, Zero));
vectorField& result = tresult.ref();
...
return tresult;
NotImplemented
\since 1806
For non-implemented functions returning a tmp
, we use the C++
nullptr
which will be automatically converted to an invalid tmp
when the code is executed.
tmp<vectorField> method
{
NotImplemented;
return nullptr;
}
Anti-pattern: the older style, which is less prevalent, is to return
an invalid tmp
or an empty tmp
. The effect will be the same (since
the code will not be executed), but corresponds to more typing and we
need to match the return types (scalarField, vectorField etc).
tmp<vectorField> method
{
NotImplemented;
return tmp<vectorField>();
}
// or
tmp<vectorField> method
{
NotImplemented;
return tmp<vectorField>(new vectorField(0));
}
Return valid, zero-sized tmp field
\since 1806
When a zero-sized tmp field is required:
return tmp<vectorField>::New();
This uses forwarding to a null-constructed vectorField
, which has
zero-size.
Anti-pattern: manual allocation of the underlying field, constructing the underlying field explicitly with size 0 instead of using the null-constructed form (which is defined to be noexcept).
return tmp<vectorField>(new vectorField(0));
Handling of references or local storage
\since 2012, partly earlier
Both tmp and refPtr (a refernce and/or pointer) containers serve a similar purpose - to hold a reference or an allocated pointer to memory. The principal difference is that tmp has intrusive ref-counting and a number of OpenFOAM operations are built around it. Whereas refPtr has no ref-counting, which makes it suitable for holding any type of object.
Both tmp and refPtr can hold a const or modifiable reference or an allocated pointer. This especially makes refPtr ideal for storage and addressing. For example,
tmp<volScalarField> tfld(nullptr);
auto* ptr = getObjectPtr<volScalarField>("field");
if (ptr)
{
// using a writable reference
tfld.ref(*ptr);
}
else
{
// using an allocated pointer
tfld.reset(volScalarField::New(...));
}
auto& fld = tfld.ref();
Copyright (C) 2019-2020 OpenCFD Ltd.