BDE 4.14.0 Production release
|
Macros | |
#define | BSLALG_DECLARE_NESTED_TRAITS(T, TRAIT) |
#define | BSLALG_DECLARE_NESTED_TRAITS2(T, TRAIT1, TRAIT2) |
Like BSLALG_DECLARE_NESTED_TRAITS , but for two traits. | |
#define | BSLALG_DECLARE_NESTED_TRAITS3(T, TRAIT1, TRAIT2, TRAIT3) |
Like BSLALG_DECLARE_NESTED_TRAITS , but for three traits. | |
#define | BSLALG_DECLARE_NESTED_TRAITS4(T, TRAIT1, TRAIT2, TRAIT3, TRAIT4) |
Like BSLALG_DECLARE_NESTED_TRAITS , but for four traits. | |
#define | BSLALG_DECLARE_NESTED_TRAITS5(T, TRAIT1, TRAIT2, TRAIT3, TRAIT4, TRAIT5) |
Like BSLALG_DECLARE_NESTED_TRAITS , but for five traits. | |
#define | BDEALG_DECLARE_NESTED_TRAITS(T, TRAITS) BSLALG_DECLARE_NESTED_TRAITS(T, TRAITS) |
This alias is defined for backward compatibility. | |
#define | BDEALG_DECLARE_NESTED_TRAITS2(T, TRAIT1, TRAIT2) BSLALG_DECLARE_NESTED_TRAITS2(T, TRAIT1, TRAIT2) |
This alias is defined for backward compatibility. | |
#define | BDEALG_DECLARE_NESTED_TRAITS3(T, TRAIT1, TRAIT2, TRAIT3) BSLALG_DECLARE_NESTED_TRAITS3(T, TRAIT1, TRAIT2, TRAIT3) |
This alias is defined for backward compatibility. | |
#define | BDEALG_DECLARE_NESTED_TRAITS4(T, TRAIT1, TRAIT2, TRAIT3, TRAIT4) BSLALG_DECLARE_NESTED_TRAITS4(T, TRAIT1, TRAIT2, TRAIT3, TRAIT4) |
This alias is defined for backward compatibility. | |
#define | BDEALG_DECLARE_NESTED_TRAITS5(T, TRAIT1, TRAIT2, TRAIT3, TRAIT4, TRAIT5) BSLALG_DECLARE_NESTED_TRAITS5(T, TRAIT1,TRAIT2,TRAIT3,TRAIT4,TRAIT5) |
This alias is defined for backward compatibility. | |
#define | bdealg_HasTrait bslalg::HasTrait |
This alias is defined for backward compatibility. | |
#define | bdealg_SelectTrait bslalg::SelectTrait |
This alias is defined for backward compatibility. | |
Provide compile-time traits that can be associated with types.
std::pair
-like classesbslma
allocatorsThis component provides a set of type traits, and a set of macros used to assign traits to user-defined classes. Traits are used to enable certain optimizations or discriminations at compile-time. For instance, a class having the trait bslalg::TypeTraitBitwiseMoveable
may allow resizing an array of objects by simply calling std::memcpy
instead of invoking a copy-constructor on every object. The usage example shows how to use the bslalg::TypeTraitUsesBslmaAllocator
to propagate allocators to nested objects that may require them.
This component should be used in conjunction with other components from the package bslalg
. See the package-level documentation for an overview. The most useful classes and macros defined in this component are:
In this usage example, we show how to enable the bslma
allocator model for generic containers, by implementing simplified versions of the bslalg_constructorproxy and bslalg_scalarprimitives components. The interested reader should refer to the documentation of those components.
Suppose we want to implement a generic container of a parameterized TYPE
, which may or may not follow the bslma
allocator model. If it does, our container should pass an extra bslma::Allocator*
argument to copy construct a value; but if it does not, then passing this extra argument is going to generate a compile-time error. It thus appears we need two implementations of our container. This can be done more succinctly by encapsulating into the constructor some utilities that will, through a single interface, determine whether TYPE
has the trait bslalg::TypeTraitUsesBslmaAllocator
and copy-construct it accordingly.
The container contains a single data member of the parameterized TYPE
. Since we are going to initialize this data member manually, we do not want it to be automatically constructed by the compiler. For this reason, we encapsulate it in a bsls::ObjectBuffer
.
Since the container offers a uniform interface that always takes an extra allocator argument, regardless of whether TYPE
does or not, we can declare it to have the bslalg::TypeTraitUsesBslmaAllocator
trait:
For simplicity, we let the container contain only a single element, and require that an element always be initialized.
We can also allow the container to change the object it contains, by granting modifiable as well as non-modifiable access to this object:
The challenge in the implementation lies in using the traits of the contained TYPE
to determine whether to pass the allocator argument to its copy constructor. We rely here on a property of templates that templates are not compiled (and thus will not generate compilation errors) until they are instantiated. Hence, we can use two function templates, and let the overloading resolution (based on the nested traits) decide which to instantiate. The generic way to create an object, passing through all arguments (value and allocator) is as follows. For brevity and to avoid breaking the flow of this example, we have embedded the function definition into the class.
For types that don't use an allocator, we offer the following overload that will be selected if the type trait of TYPE
cannot be converted to bslalg::TypeTraitUsesBslmaAllocator
. In that case, note that the type traits always inherit from bslalg::TypeTraitNil
.
And finally, this function will instantiate the type trait and pass it to the appropriately (compiler-)chosen overload:
With these utilities, we can now implement MyGenericContainer
.
Note that all this machinery only affects the constructors, and not the destructor which only invokes the destructor of d_object
.
To finish, the accessors and manipulators are trivially implemented.
We can check that our container actually forwards the correct allocator to its contained objects with a very simple test apparatus, consisting of two classes that have exactly the same signature and implementation except that one has the bslalg::TypeTraitUsesBslmaAllocator
trait and the other does not:
Our verification program simply instantiates several MyGenericContainer
templates with the two test types above, and checks that the allocator slot is as expected:
With MyTestTypeWithNoBslmaAllocatorTraits
, the slot should never be set.
With MyTestTypeWithBslmaAllocatorTraits
, the slot should be set to the allocator argument, or to 0 if not specified:
#define BDEALG_DECLARE_NESTED_TRAITS | ( | T, | |
TRAITS | |||
) | BSLALG_DECLARE_NESTED_TRAITS(T, TRAITS) |
#define BDEALG_DECLARE_NESTED_TRAITS2 | ( | T, | |
TRAIT1, | |||
TRAIT2 | |||
) | BSLALG_DECLARE_NESTED_TRAITS2(T, TRAIT1, TRAIT2) |
#define BDEALG_DECLARE_NESTED_TRAITS3 | ( | T, | |
TRAIT1, | |||
TRAIT2, | |||
TRAIT3 | |||
) | BSLALG_DECLARE_NESTED_TRAITS3(T, TRAIT1, TRAIT2, TRAIT3) |
#define BDEALG_DECLARE_NESTED_TRAITS4 | ( | T, | |
TRAIT1, | |||
TRAIT2, | |||
TRAIT3, | |||
TRAIT4 | |||
) | BSLALG_DECLARE_NESTED_TRAITS4(T, TRAIT1, TRAIT2, TRAIT3, TRAIT4) |
#define BDEALG_DECLARE_NESTED_TRAITS5 | ( | T, | |
TRAIT1, | |||
TRAIT2, | |||
TRAIT3, | |||
TRAIT4, | |||
TRAIT5 | |||
) | BSLALG_DECLARE_NESTED_TRAITS5(T, TRAIT1,TRAIT2,TRAIT3,TRAIT4,TRAIT5) |
#define bdealg_HasTrait bslalg::HasTrait |
#define bdealg_SelectTrait bslalg::SelectTrait |
#define BSLALG_DECLARE_NESTED_TRAITS | ( | T, | |
TRAIT | |||
) |
Associate the specified TRAIT
tag with the specified T
class. This macro must be invoked only within the public part of the definition of class T
. TRAIT
must name a class such that TRAIT::NestedTraitDeclaration<T>
designates a class derived from bslmf::DetectNestedTrait
.
#define BSLALG_DECLARE_NESTED_TRAITS2 | ( | T, | |
TRAIT1, | |||
TRAIT2 | |||
) |
#define BSLALG_DECLARE_NESTED_TRAITS3 | ( | T, | |
TRAIT1, | |||
TRAIT2, | |||
TRAIT3 | |||
) |
#define BSLALG_DECLARE_NESTED_TRAITS4 | ( | T, | |
TRAIT1, | |||
TRAIT2, | |||
TRAIT3, | |||
TRAIT4 | |||
) |
#define BSLALG_DECLARE_NESTED_TRAITS5 | ( | T, | |
TRAIT1, | |||
TRAIT2, | |||
TRAIT3, | |||
TRAIT4, | |||
TRAIT5 | |||
) |