Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bslma_usesbslmaallocator
[Package bslma]

Provide a metafunction to indicate the use of bslma allocators. More...

Namespaces

namespace  bslma

Detailed Description

Outline
Purpose:
Provide a metafunction to indicate the use of bslma allocators.
Classes:
bslma::UsesBslmaAllocator trait detection metafunction for bslma use
See also:
bslalg_typetraitusesblsmaallocator
Description:
This component defines a metafunction, bslma::UsesBslmaAllocator, that may be used to associate a type with the uses-'bslma'-allocator trait (i.e., declare that a type uses a bslma allocator), and also to detect whether a type has been associated with that trait (i.e., to test whether a type uses a bslma allocator, and follows the bslma allocator model).
Properties of Types Declaring the UsesBslmaAllocator Trait:
Types that declare the UsesBslmaAllocator trait must meet some minimal requirements in order for that type to be usable with code that tests for the UsesBslmaAllocator trait (e.g., bsl containers). In addition, types that use allocators must have certain properties with respect to memory allocation, which are not enforced by the compiler (such a type is described as following the bslma allocator model).
Compiler-Enforced Requirements of Types Declaring UsesBslmaAllocator:
Types declaring the UsesBslmaAllocator trait must provide a constructor variant that accepts a bslma::Allocator * as the last argument (typically this is an optional argument). If such a type provides a copy constructor, it must similarly provide a variant that takes a (optional) bslma::Allocator * as the last argument. If such a type provides a move constructor, it must similarly provide a variant that takes a bslma::Allocator * as the last argument.
Template types (such as bsl containers), where the template parameter TYPE represents some element type encapsulated by the class template, often use the UsesBslmaAllocator trait to test if TYPE uses bslma allocators and, if so, to create TYPE objects using the constructor variant taking an allocator. In this context, compilation will fail if a type declares the UsesBslmaAllocator trait, but does not provide the expected constructor variant accepting a bslma::Allocator * as the last argument.
Expected Properties of Types Declaring the UsesBslmaAllocator Trait:
Types declaring the UsesBslmaAllocator trait are expected to have certain properties with respect to memory allocation. These properties are not enforced by the compiler, but are necessary to ensure consistent and comprehensible allocation behavior.
  • The allocator supplied at construction of an object will be used for non-transient memory allocation during the object's lifetime. This particularly includes allocations performed by sub-objects that themselves support the bslma allocator model (i.e., the type will provide the supplied allocator to any data members that themselves accept an allocator).
  • If the type defines a move constructor with an allocator parameter:

    1. If another move constructor without an allocator parameter that is noexcept exists, then if the allocators match, the behavior of those two move constructors will be identical.
    2. If the type defines a copy constructor, then the behavior of this move constructor when allocators don't match will be the same as the behavior of the copy constructor.

  • The allocator used by an object is not changed after construction (e.g., the assignment operator does not change the allocator used by an object).
  • Transient memory allocations -- i.e., allocations performed within the scope of a function where the resulting memory is deallocated before that function returns -- are generally not performed using the object's allocator. Although clients may choose whichever allocator suits the specific context, most often transient memory allocations are performed using the currently installed default allocator. For example, a temporary bsl::string that is destroyed within the scope of a method need not be explicitly supplied an allocator, since it is a transient allocation, and bsl::string will use the default allocator by default.
  • The allocator used by an object is not part of an object's value (e.g., it is not tested by the equality-comparison operator operator==).
  • If an allocator is not supplied at construction, then the currently installed default allocator will typically be used (see bslma_default).
  • If a move constructor is called with no allocator argument, the allocator used by the new object will be the same as the allocator used by the source object.
  • Singleton objects, when necessary, allocate memory from the global allocator (see bslma_default).
Usage:
This section illustrates intended usage of this component.
Example 1: Associating the bslma Allocator Trait with a Type:
Suppose we want to declare two types that make use of a bslma allocator, and need to associate the UsesBslmaAllocator trait with those types (so that they behave correctly when inserted into a bsl container, for example). In this example we will demonstrate two different mechanisms by which a trait may be associated with a type.
First, we define a type UsesAllocatorType1 and use the BSLMF_NESTED_TRAIT_DECLARATION macro to associate the type with the UsesBslmaAllocator trait:
  namespace xyz {

  class UsesAllocatorType1 {
      // ...

    public:
      // TRAITS
      BSLMF_NESTED_TRAIT_DECLARATION(UsesAllocatorType1,
                                     bslma::UsesBslmaAllocator);
      // CREATORS
      explicit UsesAllocatorType1(bslma::Allocator *basicAllocator = 0);
          // ...

      UsesAllocatorType1(const UsesAllocatorType1&  original,
                         bslma::Allocator          *basicAllocator = 0);
          // ...
  };
Notice that the macro declaration is performed within the scope of the class declaration, and must be done with public access.
Then, we define a type UsesAllocatorType2 and define a specialization of the UsesBslmaAllocator trait for UsesAllocatorType2 that associates the UsesBslmaAllocator trait with the type (note that this is sometimes referred to as a "C++11-style" trait declaration, since it is more in keeping with the style of trait declarations found in the C++11 Standard):
  class UsesAllocatorType2 {
      // ...

    public:
      // CREATORS
      explicit UsesAllocatorType2(bslma::Allocator *basicAllocator = 0);
          // ...

      UsesAllocatorType2(const UsesAllocatorType2&  original,
                         bslma::Allocator          *basicAllocator = 0);
          // ...
  };

  }  // close package namespace

  // TRAITS
  namespace BloombergLP {
  namespace bslma {

  template <> struct UsesBslmaAllocator<xyz::UsesAllocatorType2> :
                                                               bsl::true_type
  {};

  }  // close namespace bslma
  }  // close enterprise namespace
Notice that the specialization must be performed in the BloombergLP::bslma namespace.
Example 2: Testing Whether a Type Uses a bslma Allocator:
Suppose we want to test whether each of a set of different types uses a bslma allocator.
Here, we use the UsesBslmaAllocator template to test whether the types DoesNotUseAnAllocatorType, UsesAllocatorType1, and UsesAllocatorType2 (see above for the latter two types) use allocators: Finally, we demonstrate that the trait can be tested at compilation time by testing the trait within the context of a compile-time BSLMF_ASSERT: