Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bslma_rawdeleterguard
[Package bslma]

Provide a guard to unconditionally manage an object. More...

Namespaces

namespace  bslma

Detailed Description

Outline
Purpose:
Provide a guard to unconditionally manage an object.
Classes:
bslma::RawDeleterGuard guard to unconditionally manage an object
See also:
Component bslma_rawdeleterproctor, Component bslma_autorawdeleter
Description:
This component provides a guard class template, bslma::RawDeleterGuard, to unconditionally manage an (otherwise-unmanaged) object of parameterized TYPE supplied at construction. The managed object is deleted automatically when the guard object goes out of scope by first calling the (managed) object's destructor, and then freeing the memory using the parameterized ALLOCATOR (allocator or pool) also supplied at construction.
Raw
Warning: Note that this component should be used only if we are sure that the supplied pointer is not of a type that is a secondary base class -- i.e., the (managed) object's address is (numerically) the same as when it was originally dispensed by ALLOCATOR.
Requirement:
The parameterized ALLOCATOR type of the bslma::RawDeleterGuard class template must provide a (possibly virtual) method:
  void deallocate(void *address);
to deallocate memory at the specified address (originally supplied by the ALLOCATOR object).
Usage:
This example shows how one might use a bslma::RawDeleterGuard to guard a dynamically-allocated object, deleting that object automatically when the guard goes out of scope.
Suppose we have a simple queue class that stores object values using an "out-of-place" representation (i.e., an array of dynamically-allocated object pointers):
  // my_queue.h
  // ...

  template <class TYPE>
  class my_Queue {
      // This class is a container that uses an "out-of-place"
      // representation to manage objects of parameterized 'TYPE'.  Note
      // that this class is implemented with the native version of 'deque',
      // instead of the version provided in 'bslstl_Deque'.  This is so that
      // a circular dependency in the physical hierarchy will not be created.

      // DATA
      std::deque<TYPE *>   d_objects;      // objects stored in the queue
      bslma::Allocator    *d_allocator_p;  // allocator (held, not owned)

    public:
      // CREATORS
      my_Queue(bslma::Allocator *basicAllocator = 0);
          // Create a 'my_Queue' object.  Optionally specify a
          // 'basicAllocator' used to supply memory.  If 'basicAllocator' is
          // 0, the currently installed default allocator is used.

      // ...

      ~my_Queue();
          // Destroy this 'my_Queue' object and all elements currently
          // stored.

      // MANIPULATORS

      // ...

      void pushBack(const TYPE& object);
          // Push the value of the specified 'object' of parameterized 'TYPE'
          // onto the back of this queue.

      TYPE popFront();
          // Remove and return (by value) the object of parameterized 'TYPE'
          // that is currently at the front of this queue.

      // ...
  };
Note that the popFront method returns an object by value because (1) there may be no reasonable default object to pass in, (2) there may be no reasonable copy-assignment semantics, or (3) it is simply more syntactically convenient (e.g., if, say, the queued objects are themselves pointers):
  // CREATORS
  template <class TYPE>
  inline
  my_Queue<TYPE>::my_Queue(bslma::Allocator *basicAllocator)
  : d_objects(basicAllocator)
  , d_allocator_p(bslma::Default::allocator(basicAllocator))
  {
  }

  template <class TYPE>
  my_Queue<TYPE>::~my_Queue()
  {
      for (int i = 0; i < d_objects.size(); ++i) {
          d_allocator_p->deleteObjectRaw(d_objects[i]);
      }
  }
Note that the pushBack method should be implemented with a constructor proxy that determines whether TYPE takes an allocator at construction (see bslalg_constructorproxy). However, for the purpose of this example, the implementation is simplified by assuming TYPE takes an allocator.
  // MANIPULATORS
  template <class TYPE>
  inline
  void my_Queue<TYPE>::pushBack(const TYPE& object)
  {
      TYPE *tmp = (TYPE *)new(*d_allocator_p) TYPE(object);
      d_objects.push_back(tmp);
  }

  template <class TYPE>
  inline
  TYPE my_Queue<TYPE>::popFront()
  {
      TYPE *tmp = d_objects.front();
      d_objects.pop_front();

      //***********************************************************
      //* Note the use of the raw deleter guard on 'tmp' (below). *
      //***********************************************************

      bslma::RawDeleterGuard<TYPE, bslma::Allocator>
                                                   guard(tmp, d_allocator_p);

      return *tmp;
  }
The pushBack method defined above stores a copy of the provided object. The popFront method returns the leading object by value, and the bslma::RawDeleterGuard is used to automatically delete the copy the queue manages when the guard goes out of scope (i.e., when the function returns).