BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslma_managedptr.h
Go to the documentation of this file.
1/// @file bslma_managedptr.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_managedptr.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_MANAGEDPTR
9#define INCLUDED_BSLMA_MANAGEDPTR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id$ $CSID$")
13
14/// @defgroup bslma_managedptr bslma_managedptr
15/// @brief Provide a managed pointer class.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_managedptr
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_managedptr-purpose"> Purpose</a>
25/// * <a href="#bslma_managedptr-classes"> Classes </a>
26/// * <a href="#bslma_managedptr-description"> Description </a>
27/// * <a href="#bslma_managedptr-factories"> Factories </a>
28/// * <a href="#bslma_managedptr-deleters"> Deleters </a>
29/// * <a href="#bslma_managedptr-aliasing"> Aliasing </a>
30/// * <a href="#bslma_managedptr-exception-safety"> Exception Safety </a>
31/// * <a href="#bslma_managedptr-type-casting"> Type Casting </a>
32/// * <a href="#bslma_managedptr-explicit-casting"> Explicit Casting </a>
33/// * <a href="#bslma_managedptr-implicit-casting"> Implicit Casting </a>
34/// * <a href="#bslma_managedptr-usage"> Usage </a>
35/// * <a href="#bslma_managedptr-example-1-implementing-a-protocol"> Example 1: Implementing a Protocol </a>
36/// * <a href="#bslma_managedptr-example-2-aliasing"> Example 2: Aliasing </a>
37/// * <a href="#bslma_managedptr-example-3-dynamic-objects-and-factories"> Example 3: Dynamic Objects and Factories </a>
38/// * <a href="#bslma_managedptr-example-4-type-casting"> Example 4: Type Casting </a>
39/// * <a href="#bslma_managedptr-implicit-conversion"> Implicit Conversion </a>
40/// * <a href="#bslma_managedptr-explicit-conversion"> Explicit Conversion </a>
41/// * <a href="#bslma_managedptr-example-5-inplace-object-creation"> Example 5: Inplace Object Creation </a>
42///
43/// # Purpose {#bslma_managedptr-purpose}
44/// Provide a managed pointer class.
45///
46/// # Classes {#bslma_managedptr-classes}
47///
48/// - bslma::ManagedPtr: proctor for automatic memory management
49/// - bslma::ManagedPtrUtil: namespace for `ManagedPtr`-related utility functions
50///
51/// @see bslmf_ispolymporphic
52///
53/// # Description {#bslma_managedptr-description}
54/// This component provides a proctor, `bslma::ManagedPtr`, similar
55/// to `bsl::auto_ptr`, that supports user-specified deleters. The proctor is
56/// responsible for the automatic destruction of the object referenced by the
57/// managed pointer. As a "smart pointer", this object offers an interface
58/// similar to a native pointer, supporting dereference operators (*, ->),
59/// (in)equality comparison and testing as if it were a boolean value. However,
60/// like `bsl::auto_ptr` it has unusual "copy-semantics" that transfer ownership
61/// of the managed object, rather than making a copy. It should be noted that
62/// this signature does not satisfy the requirements for an element-type stored
63/// in any of the standard library containers. Note that this component will
64/// fail to compile when instantiated for a class that gives a false-positive
65/// for the type trait `bslmf::IsPolymorphic`. See the @ref bslmf_ispolymporphic
66/// component for more details.
67///
68/// This component also provides the `bslma::ManagedPtrUtil` `struct`, which
69/// defines a namespace for utility functions that facilitate working with
70/// `ManagedPtr` objects. Of particular note are the `allocateManaged` and
71/// `makeManaged` class methods that can be used to create a managed object as
72/// well as a `ManagedPtr` to manage it, with the latter being returned.
73/// `allocateManaged` takes a `bslma::Allocator *` argument that is both (1)
74/// used to allocate the footprint of the managed object and (2) used by the
75/// managed object itself if it defines the `bslma::UsesBslmaAllocator` trait.
76/// `makeManaged` does not take a `bslma::Allocator *` argument and uses the
77/// default allocator to allocate the footprint of the managed object instead.
78///
79/// ## Factories {#bslma_managedptr-factories}
80///
81///
82/// An object that will be managed by a `ManagedPtr` object is typically
83/// dynamically allocated and destroyed by a factory. For the purposes of this,
84/// component, a factory is any class that provides a `deleteObject` function
85/// taking a single argument of the (pointer) type of the managed pointer. The
86/// following is an example of a factory deleter:
87/// @code
88/// class my_Factory {
89///
90/// // . . .
91///
92/// // MANIPULATORS
93///
94/// /// Create a `my_Type` object. Optionally specify a
95/// /// `basicAllocator` used to supply memory. If `basicAllocator` is
96/// /// 0, the currently installed default allocator is used.
97/// my_Type *createObject(bslma::Allocator *basicAllocator = 0);
98///
99/// /// Delete the specified `object`.
100/// void deleteObject(my_Type *object);
101/// };
102///
103/// class my_Allocator : public bslma::Allocator { /* ... */ };
104/// @endcode
105/// Note that `deleteObject` is provided by all `bslma` allocators and by any
106/// object that implements the `bdlma::Deleter` protocol. Thus, any of these
107/// objects can be used as a factory deleter. The purpose of this design is to
108/// allow `bslma` allocators and factories to be used seamlessly as deleters.
109///
110/// Note that when the `ManagedPtr(MANAGED_TYPE *)` constructor is used, the
111/// managed object will be destroyed with a built-in deleter that calls
112/// `delete ptr`, but when the `ManagedPtr(MANAGED_TYPE *, FACTORY_TYPE *)`
113/// constructor is called with `0 == factory`, the currently installed default
114/// allocator will be used as the factory.
115///
116/// ## Deleters {#bslma_managedptr-deleters}
117///
118///
119/// When a managed pointer is destroyed, the managed object is destroyed using
120/// the user supplied "deleter". A deleter is simply a function that is invoked
121/// with two `void *` arguments: a pointer to the object to be destroyed, and a
122/// pointer to a `cookie` that is supplied at the same time as the `deleter` and
123/// managed object.
124/// @code
125/// typedef void (*DeleterFunc)(void *managedObject, void *cookie);
126/// @endcode
127/// The meaning of the `cookie` depends on the specific deleter. Typically a
128/// deleter function will accept the two `void *` pointers and internally cast
129/// them to the appropriate types for pointers to the managed object and
130/// `cookie`. Note that there are no methods taking just a deleter, as the user
131/// must always supply a `cookie` to be passed when the deleter is actually
132/// invoked.
133///
134/// Note that this component still supports (deprecated) legacy deleters that
135/// expect to be passed pointers to the specific `cookie` and managed object
136/// types in use. This latter form of deleter was deprecated as it relies on
137/// undefined behavior, casting such function pointers to the correct form
138/// (taking two `void *` arguments) and invoking the function with two `void *`
139/// pointer arguments. While this is undefined behavior, it is known to have
140/// the desired effect on all platforms currently in use.
141///
142/// ## Aliasing {#bslma_managedptr-aliasing}
143///
144///
145/// In a managed pointer, the pointer value (the value returned by the `get`
146/// method) and the pointer to the managed object need not have the same value.
147/// The `loadAlias` method allows a managed pointer to be created as an "alias"
148/// to another managed pointer (possibly of a different type), which we'll call
149/// the "original" managed pointer. When `get` is invoked on the alias, the
150/// aliased pointer value is returned, but when the managed pointer is
151/// destroyed, the original managed object will be passed to the deleter. (See
152/// also the documentation of the `alias` constructor or of the `loadAlias`
153/// method.)
154///
155/// ## Exception Safety {#bslma_managedptr-exception-safety}
156///
157///
158/// The principal usage of a managed pointer is to guarantee that a local object
159/// will be deallocated properly should an operation throw after its allocation.
160/// In this, it is very similar to `bsl::auto_ptr`. It is required for the
161/// proper functioning of this component that a deleter does not throw at
162/// invocation (upon destruction or re-assignment of the managed pointer).
163///
164/// ## Type Casting {#bslma_managedptr-type-casting}
165///
166///
167/// `ManagedPtr` objects can be implicitly and explicitly cast to different
168/// types in the same way that native pointers can.
169///
170/// ### Explicit Casting {#bslma_managedptr-explicit-casting}
171///
172///
173/// Through "aliasing", a managed pointer of any type can be explicitly cast to
174/// a managed pointer of any other type using any legal cast expression. See
175/// example 4 on `type casting` below for more details.
176///
177/// ### Implicit Casting {#bslma_managedptr-implicit-casting}
178///
179///
180/// As with native pointers, a managed pointer of the type `B` that is derived
181/// from the type `A`, can be directly assigned to a `ManagedPtr` of `A`.
182/// Likewise a managed pointer of type `B` can be directly assigned to a
183/// `ManagedPtr` of `const B`. However, the rules for construction are a little
184/// more subtle, and apply when passing a `bslma::ManagedPtr` by value into a
185/// function, or returning as the result of a function.
186/// @code
187/// class A {};
188///
189/// class B : public A {};
190///
191/// void test()
192/// {
193/// B *b_p = 0;
194/// A *a_p = b_p;
195///
196/// bslma::ManagedPtr<B> b_mp1;
197/// bslma::ManagedPtr<A> a_mp1(b_mp1); // direct-initialization is valid
198/// bslma::ManagedPtr<A> a_mp2 = b_mp1; // copy-initialization should fail
199/// }
200/// @endcode
201/// Note that `std::auto_ptr` has the same restriction, and this failure will
202/// occur only on compilers that strictly conform to the C++ standard, such as
203/// recent gcc compilers or (in this case) IBM xlC.
204///
205/// ## Usage {#bslma_managedptr-usage}
206///
207///
208/// In this section we show intended usage of this component.
209///
210/// ### Example 1: Implementing a Protocol {#bslma_managedptr-example-1-implementing-a-protocol}
211///
212///
213/// We demonstrate using `ManagedPtr` to configure and return a managed object
214/// implementing an abstract protocol.
215///
216/// First we define our protocol, `Shape`, a type of object that knows how to
217/// compute its `area`. Note that for expository reasons only, we do *not* give
218/// `Shape` a virtual destructor.
219/// @code
220/// struct Shape {
221/// /// Return the `area` of this shape.
222/// virtual double area() const = 0;
223/// };
224/// @endcode
225/// Then we define a couple of classes that implement the `Shape` protocol, a
226/// `Circle` and a `Square`.
227/// @code
228/// class Circle : public Shape {
229/// private:
230/// // DATA
231/// double d_radius;
232///
233/// public:
234/// // CREATORS
235///
236/// /// Create a `Circle` object having the specified `radius`.
237/// explicit Circle(double radius);
238///
239/// /// Destroy this object.
240/// virtual ~Circle();
241///
242/// // ACCESSORS
243///
244/// /// Return the area of this Circle, given by the formula pi*r*r.
245/// virtual double area() const;
246/// };
247///
248/// class Square : public Shape {
249/// private:
250/// // DATA
251/// double d_sideLength;
252///
253/// public:
254/// // CREATORS
255///
256/// /// Create a `Square` having sides of length `side`.
257/// explicit Square(double side);
258///
259/// /// Destroy this object.
260/// virtual ~Square();
261///
262/// // ACCESSORS
263///
264/// /// Return the area of this Square, given by the formula side*side
265/// virtual double area() const;
266/// };
267/// @endcode
268/// Next we implement the methods for `Circle` and `Square`.
269/// @code
270/// Circle::Circle(double radius)
271/// : d_radius(radius)
272/// {
273/// }
274///
275/// Circle::~Circle()
276/// {
277/// }
278///
279/// double Circle::area() const {
280/// return 3.141592653589793238462 * d_radius * d_radius;
281/// }
282///
283/// Square::Square(double side)
284/// : d_sideLength(side)
285/// {
286/// }
287///
288/// Square::~Square()
289/// {
290/// }
291///
292/// double Square::area() const {
293/// return d_sideLength * d_sideLength;
294/// }
295/// @endcode
296/// Then we define an enumeration that lists each implementation of the `Shape`
297/// protocol.
298/// @code
299/// struct Shapes {
300/// enum VALUES { SHAPE_CIRCLE, SHAPE_SQUARE };
301/// };
302/// @endcode
303/// Now we can define a function that will return a `Circle` object or a
304/// `Square` object according to the specified `kind` parameter, and having its
305/// `dimension` specified by the caller.
306/// @code
307/// bslma::ManagedPtr<Shape> makeShape(Shapes::VALUES kind, double dimension)
308/// {
309/// bslma::Allocator *alloc = bslma::Default::defaultAllocator();
310/// bslma::ManagedPtr<Shape> result;
311/// switch (kind) {
312/// case Shapes::SHAPE_CIRCLE: {
313/// Circle *circ = new(*alloc)Circle(dimension);
314/// result.load(circ);
315/// } break;
316/// case Shapes::SHAPE_SQUARE: {
317/// Square *sqr = new(*alloc)Square(dimension);
318/// result.load(sqr);
319/// } break;
320/// }
321/// return result;
322/// }
323/// @endcode
324/// Then, we can use our function to create shapes of different kinds, and check
325/// that they report the correct area. Note that we are using a radius of `1.0`
326/// for the `Circle` and integral side-length for the `Square` to support an
327/// accurate `operator==` with floating-point quantities. Also note that,
328/// despite the destructor for `Shape` being non-virtual, the correct destructor
329/// for the appropriate concrete `Shape` type is called. This is because the
330/// destructor is captured when the `ManagedPtr` constructor is called, and has
331/// access to the complete type of each shape object.
332/// @code
333/// void testShapes()
334/// {
335/// bslma::ManagedPtr<Shape> shape = makeShape(Shapes::SHAPE_CIRCLE, 1.0);
336/// assert(0 != shape);
337/// assert(3.141592653589793238462 == shape->area());
338///
339/// shape = makeShape(Shapes::SHAPE_SQUARE, 2.0);
340/// assert(0 != shape);
341/// assert(4.0 == shape->area());
342/// }
343/// @endcode
344/// Next, we observe that as we are creating objects dynamically, we should pass
345/// an allocator to the `makeShape` function, rather than simply accepting the
346/// default allocator each time. Note that when we do this, we pass the user's
347/// allocator to the `ManagedPtr` object as the "factory".
348/// @code
349/// bslma::ManagedPtr<Shape> makeShape(Shapes::VALUES kind,
350/// double dimension,
351/// bslma::Allocator *allocator)
352/// {
353/// bslma::Allocator *alloc = bslma::Default::allocator(allocator);
354/// bslma::ManagedPtr<Shape> result;
355/// switch (kind) {
356/// case Shapes::SHAPE_CIRCLE: {
357/// Circle *circ = new(*alloc)Circle(dimension);
358/// result.load(circ, alloc);
359/// } break;
360/// case Shapes::SHAPE_SQUARE: {
361/// Square *sqr = new(*alloc)Square(dimension);
362/// result.load(sqr, alloc);
363/// } break;
364/// }
365/// return result;
366/// }
367/// @endcode
368/// Finally we repeat the earlier test, additionally passing a test allocator:
369/// @code
370/// void testShapesToo()
371/// {
372/// bslma::TestAllocator ta("object");
373///
374/// bslma::ManagedPtr<Shape> shape =
375/// makeShape(Shapes::SHAPE_CIRCLE, 1.0, &ta);
376/// assert(0 != shape);
377/// assert(3.141592653589793238462 == shape->area());
378///
379/// shape = makeShape(Shapes::SHAPE_SQUARE, 3.0, &ta);
380/// assert(0 != shape);
381/// assert(9.0 == shape->area());
382/// }
383/// @endcode
384///
385/// ### Example 2: Aliasing {#bslma_managedptr-example-2-aliasing}
386///
387///
388/// Suppose that we wish to give access to an item in a temporary array via a
389/// pointer, which we will call the "finger". The finger is the only pointer to
390/// the array or any part of the array, but the entire array must be valid until
391/// the finger is destroyed, at which time the entire array must be deleted. We
392/// handle this situation by first creating a managed pointer to the entire
393/// array, then creating an alias of that pointer for the finger. The finger
394/// takes ownership of the array instance, and when the finger is destroyed, it
395/// is the array's address, rather than the finger, that is passed to the
396/// deleter.
397///
398/// First, let's say our array stores data acquired from a ticker plant
399/// accessible by a global `getQuote` function:
400/// @code
401/// struct Ticker {
402///
403/// static double getQuote() // From ticker plant. Simulated here
404/// {
405/// static const double QUOTES[] = {
406/// 7.25, 12.25, 11.40, 12.00, 15.50, 16.25, 18.75, 20.25, 19.25, 21.00
407/// };
408/// static const int NUM_QUOTES = sizeof(QUOTES) / sizeof(QUOTES[0]);
409/// static int index = 0;
410///
411/// double ret = QUOTES[index];
412/// index = (index + 1) % NUM_QUOTES;
413/// return ret;
414/// }
415/// };
416/// @endcode
417/// Then, we want to find the first quote larger than a specified threshold, but
418/// would also like to keep the earlier and later quotes for possible
419/// examination. Our `getFirstQuoteLargerThan` function must allocate memory
420/// for an array of quotes (the threshold and its neighbors). It thus returns a
421/// managed pointer to the desired value:
422/// @code
423/// const double END_QUOTE = -1;
424///
425/// bslma::ManagedPtr<double> getFirstQuoteLargerThan(
426/// double threshold,
427/// bslma::Allocator *allocator)
428/// {
429/// assert(END_QUOTE < 0 && 0 <= threshold);
430/// @endcode
431/// Next, we allocate our array with extra room to mark the beginning and end
432/// with a special `END_QUOTE` value:
433/// @code
434/// const int MAX_QUOTES = 100;
435/// int numBytes = (MAX_QUOTES + 2) * sizeof(double);
436/// double *quotes = (double *) allocator->allocate(numBytes);
437/// quotes[0] = quotes[MAX_QUOTES + 1] = END_QUOTE;
438/// @endcode
439/// Then, we create a managed pointer to the entire array:
440/// @code
441/// bslma::ManagedPtr<double> managedQuotes(quotes, allocator);
442/// @endcode
443/// Next, we read quotes until the array is full, keeping track of the first
444/// quote that exceeds the threshold.
445/// @code
446/// double *finger = 0;
447///
448/// for (int i = 1; i <= MAX_QUOTES; ++i) {
449/// double quote = Ticker::getQuote();
450/// quotes[i] = quote;
451/// if (!finger && quote > threshold) {
452/// finger = &quotes[i];
453/// }
454/// }
455/// @endcode
456/// Now, we use the alias constructor to create a managed pointer that points to
457/// the desired value (the finger) but manages the entire array:
458/// @code
459/// return bslma::ManagedPtr<double>(managedQuotes, finger);
460/// }
461/// @endcode
462/// Then, our main program calls `getFirstQuoteLargerThan` like this:
463/// @code
464/// int aliasExample()
465/// {
466/// bslma::TestAllocator ta;
467/// bslma::ManagedPtr<double> result = getFirstQuoteLargerThan(16.00, &ta);
468/// assert(*result > 16.00);
469/// assert(1 == ta.numBlocksInUse());
470/// if (g_verbose) bsl::cout << "Found quote: " << *result << bsl::endl;
471/// @endcode
472/// Next, we also print the preceding 5 quotes in last-to-first order:
473/// @code
474/// if (g_verbose) bsl::cout << "Preceded by:";
475/// int i;
476/// for (i = -1; i >= -5; --i) {
477/// double quote = result.get()[i];
478/// if (END_QUOTE == quote) {
479/// break;
480/// }
481/// assert(quote < *result);
482/// if (g_verbose) bsl::cout << ' ' << quote;
483/// }
484/// if (g_verbose) bsl::cout << bsl::endl;
485/// @endcode
486/// Then, to move the finger, e.g., to the last position printed, one must be
487/// careful to retain the ownership of the entire array. Using the statement
488/// `result.load(result.get()-i)` would be an error, because it would first
489/// compute the pointer value `result.get()-i` of the argument, then release the
490/// entire array before starting to manage what has now become an invalid
491/// pointer. Instead, `result` must retain its ownership to the entire array,
492/// which can be attained by:
493/// @code
494/// result.loadAlias(result, result.get()-i);
495/// @endcode
496/// Finally, if we reset the result pointer, the entire array is deallocated:
497/// @code
498/// result.reset();
499/// assert(0 == ta.numBlocksInUse());
500/// assert(0 == ta.numBytesInUse());
501///
502/// return 0;
503/// }
504/// @endcode
505///
506/// ### Example 3: Dynamic Objects and Factories {#bslma_managedptr-example-3-dynamic-objects-and-factories}
507///
508///
509/// Suppose we want to track the number of objects currently managed by
510/// `ManagedPtr` objects.
511///
512/// First we define a factory type that holds an allocator and a usage-counter.
513/// Note that such a type cannot sensibly be copied, as the notion `count`
514/// becomes confused.
515/// @code
516/// class CountedFactory {
517/// // DATA
518/// int d_count;
519/// bslma::Allocator *d_allocator_p;
520///
521/// private:
522/// // NOT IMPLEMENTED
523/// CountedFactory(const CountedFactory&);
524/// CountedFactory& operator=(const CountedFactory&);
525///
526/// public:
527/// // CREATORS
528///
529/// /// Create a `CountedFactory` object which uses the supplied
530/// /// allocator `alloc`.
531/// explicit CountedFactory(bslma::Allocator *alloc = 0);
532///
533/// /// Destroy this object.
534/// ~CountedFactory();
535/// @endcode
536/// Next, we provide the `createObject` and `deleteObject` functions that are
537/// standard for factory objects. Note that the `deleteObject` function
538/// signature has the form required by `bslma::ManagedPtr` for a factory.
539/// @code
540/// // MANIPULATORS
541///
542/// /// Return a pointer to a newly allocated object of type `TYPE`
543/// /// created using its default constructor. Memory for the object
544/// /// is supplied by the allocator supplied to this factory's
545/// /// constructor, and the count of valid object is incremented.
546/// template <class TYPE>
547/// TYPE *createObject();
548///
549/// /// Destroy the object pointed to by `target` and reclaim the
550/// /// memory. Decrement the count of currently valid objects.
551/// template <class TYPE>
552/// void deleteObject(const TYPE *target);
553/// @endcode
554/// Then, we round out the class with the ability to query the `count` of
555/// currently allocated objects.
556/// @code
557/// // ACCESSORS
558/// int count() const;
559/// // Return the number of currently valid objects allocated by this
560/// // factory.
561/// };
562/// @endcode
563/// Next, we define the operations declared by the class.
564/// @code
565/// CountedFactory::CountedFactory(bslma::Allocator *alloc)
566/// : d_count(0)
567/// , d_allocator_p(bslma::Default::allocator(alloc))
568/// {
569/// }
570///
571/// CountedFactory::~CountedFactory()
572/// {
573/// assert(0 == d_count);
574/// }
575///
576/// template <class TYPE>
577/// TYPE *CountedFactory::createObject()
578/// {
579/// TYPE *result = new(*d_allocator_p)TYPE;
580/// ++d_count;
581/// return result;
582/// }
583///
584/// template <class TYPE>
585/// void CountedFactory::deleteObject(const TYPE *object)
586/// {
587/// d_allocator_p->deleteObject(object);
588/// --d_count;
589/// }
590///
591/// inline
592/// int CountedFactory::count() const
593/// {
594/// return d_count;
595/// }
596/// @endcode
597/// Then, we can create a test function to illustrate how such a factory would
598/// be used with `ManagedPtr`.
599/// @code
600/// void testCountedFactory()
601/// {
602/// @endcode
603/// Next, we declare a test allocator, and an object of our `CountedFactory`
604/// type using that allocator.
605/// @code
606/// bslma::TestAllocator ta;
607/// CountedFactory cf(&ta);
608/// @endcode
609/// Then, we open a new local scope and declare an array of managed pointers.
610/// We need a local scope in order to observe the behavior of the destructors at
611/// end of the scope, and use an array as an easy way to count more than one
612/// object.
613/// @code
614/// {
615/// bslma::ManagedPtr<int> pData[4];
616/// @endcode
617/// Next, we load each managed pointer in the array with a new `int` using our
618/// factory `cf` and assert that the factory `count` is correct after each new
619/// `int` is created.
620/// @code
621/// int i = 0;
622/// while (i != 4) {
623/// pData[i++].load(cf.createObject<int>(), &cf);
624/// assert(cf.count() == i);
625/// }
626/// @endcode
627/// Then, we `reset` the contents of a single managed pointer in the array, and
628/// assert that the factory `count` is appropriately reduced.
629/// @code
630/// pData[1].reset();
631/// assert(3 == cf.count());
632/// @endcode
633/// Next, we `load` a managed pointer with another new `int` value, again using
634/// `cf` as the factory, and assert that the `count` of valid objects remains
635/// the same (destroy one object and add another).
636/// @code
637/// pData[2].load(cf.createObject<int>(), &cf);
638/// assert(3 == cf.count());
639/// }
640/// @endcode
641/// Finally, we allow the array of managed pointers to go out of scope and
642/// confirm that when all managed objects are destroyed, the factory `count`
643/// falls to zero, and does not overshoot.
644/// @code
645/// assert(0 == cf.count());
646/// }
647/// @endcode
648///
649/// ### Example 4: Type Casting {#bslma_managedptr-example-4-type-casting}
650///
651///
652/// `ManagedPtr` objects can be implicitly and explicitly cast to different
653/// types in the same way that native pointers can.
654///
655/// #### Implicit Conversion {#bslma_managedptr-implicit-conversion}
656///
657///
658/// As with native pointers, a pointer of the type `B` that is publicly derived
659/// from the type `A`, can be directly assigned a `ManagedPtr` of `A`.
660///
661/// First, consider the following code snippets:
662/// @code
663/// void implicitCastingExample()
664/// {
665/// @endcode
666/// If the statements:
667/// @code
668/// bslma::TestAllocator localDefaultTa;
669/// bslma::TestAllocator localTa;
670///
671/// bslma::DefaultAllocatorGuard guard(&localDefaultTa);
672///
673/// int numdels = 0;
674///
675/// {
676/// B *b_p = 0;
677/// A *a_p = b_p;
678/// @endcode
679/// are legal expressions, then the statements
680/// @code
681/// bslma::ManagedPtr<A> a_mp1;
682/// bslma::ManagedPtr<B> b_mp1;
683///
684/// assert(!a_mp1 && !b_mp1);
685///
686/// a_mp1 = b_mp1; // conversion assignment of nil ptr to nil
687/// assert(!a_mp1 && !b_mp1);
688///
689/// B *b_p2 = new (localDefaultTa) B(&numdels);
690/// bslma::ManagedPtr<B> b_mp2(b_p2); // default allocator
691/// assert(!a_mp1 && b_mp2);
692///
693/// a_mp1 = b_mp2; // conversion assignment of non-nil ptr to nil
694/// assert(a_mp1 && !b_mp2);
695///
696/// B *b_p3 = new (localTa) B(&numdels);
697/// bslma::ManagedPtr<B> b_mp3(b_p3, &localTa);
698/// assert(a_mp1 && b_mp3);
699///
700/// a_mp1 = b_mp3; // conversion assignment of non-nil to non-nil
701/// assert(a_mp1 && !b_mp3);
702///
703/// a_mp1 = b_mp3; // conversion assignment of nil to non-nil
704/// assert(!a_mp1 && !b_mp3);
705///
706/// // constructor conversion init with nil
707/// bslma::ManagedPtr<A> a_mp4(b_mp3, b_mp3.get());
708/// assert(!a_mp4 && !b_mp3);
709///
710/// // constructor conversion init with non-nil
711/// B *p_b5 = new (localTa) B(&numdels);
712/// bslma::ManagedPtr<B> b_mp5(p_b5, &localTa);
713/// bslma::ManagedPtr<A> a_mp5(b_mp5, b_mp5.get());
714/// assert(a_mp5 && !b_mp5);
715/// assert(a_mp5.get() == p_b5);
716///
717/// // constructor conversion init with non-nil
718/// B *p_b6 = new (localTa) B(&numdels);
719/// bslma::ManagedPtr<B> b_mp6(p_b6, &localTa);
720/// bslma::ManagedPtr<A> a_mp6(b_mp6);
721/// assert(a_mp6 && !b_mp6);
722/// assert(a_mp6.get() == p_b6);
723///
724/// struct S {
725/// int d_i[10];
726/// };
727///
728/// assert(200 == numdels);
729/// }
730///
731/// assert(400 == numdels);
732/// } // implicitCastingExample()
733/// @endcode
734///
735/// #### Explicit Conversion {#bslma_managedptr-explicit-conversion}
736///
737///
738/// Through "aliasing", a managed pointer of any type can be explicitly
739/// converted to a managed pointer of any other type using any legal cast
740/// expression. For example, to static-cast a managed pointer of type A to a
741/// managed pointer of type B, one can simply do the following:
742/// @code
743/// void explicitCastingExample() {
744///
745/// bslma::ManagedPtr<A> a_mp;
746/// bslma::ManagedPtr<B> b_mp1(a_mp, static_cast<B *>(a_mp.get()));
747/// @endcode
748/// or even use the less safe "C"-style casts:
749/// @code
750/// bslma::ManagedPtr<B> b_mp2(a_mp, (B *)(a_mp.get()));
751///
752/// } // explicitCastingExample()
753/// @endcode
754/// Note that when using dynamic cast, if the cast fails, the target managed
755/// pointer will be reset to an unset state, and the source will not be
756/// modified. Consider for example the following snippet of code:
757/// @code
758/// void processPolymorphicObject(bslma::ManagedPtr<A> aPtr,
759/// bool *castSucceeded)
760/// {
761/// bslma::ManagedPtr<B> bPtr(aPtr, dynamic_cast<B *>(aPtr.get()));
762/// if (bPtr) {
763/// assert(!aPtr);
764/// *castSucceeded = true;
765/// }
766/// else {
767/// assert(aPtr);
768/// *castSucceeded = false;
769/// }
770/// }
771/// @endcode
772/// If the value of `aPtr` can be dynamically cast to `B *` then ownership is
773/// transferred to `bPtr`; otherwise, `aPtr` is to be modified. As previously
774/// stated, the managed object will be destroyed correctly regardless of how it
775/// is cast.
776///
777/// ### Example 5: Inplace Object Creation {#bslma_managedptr-example-5-inplace-object-creation}
778///
779///
780/// Suppose we want to allocate memory for an object, construct it in place, and
781/// obtain a managed pointer referring to this object. This can be done in one
782/// step using two free functions provided in `bslma::ManagedPtrUtil`.
783///
784/// First, we create a simple class clearly showing the features of these
785/// functions. Note that this class does not define the
786/// `bslma::UsesBslmaAllocator` trait. It is done intentionally for
787/// illustration purposes only, and definitely is *not* *recommended* in
788/// production code. The class has an elided interface (i.e., copy constructor
789/// and copy-assignment operator are not included for brevity):
790/// @code
791/// /// Simple class that stores a copy of a null-terminated C-style string.
792/// class String {
793///
794/// private:
795/// // DATA
796/// char *d_str_p; // stored value (owned)
797/// bslma::Allocator *d_alloc_p; // allocator to allocate any dynamic
798/// // memory (held, not owned)
799///
800/// public:
801/// // CREATORS
802///
803/// /// Create an object having the same value as the specified `str`
804/// /// using the specified `alloc` to supply memory.
805/// String(const char *str, bslma::Allocator *alloc)
806/// : d_alloc_p(alloc)
807/// {
808/// assert(str);
809/// assert(alloc);
810///
811/// std::size_t length = std::strlen(str);
812///
813/// d_str_p = static_cast<char *>(d_alloc_p->allocate(length + 1));
814/// std::memcpy(d_str_p, str, length + 1);
815/// }
816///
817/// /// Destroy this object.
818/// ~String()
819/// {
820/// d_alloc_p->deallocate(d_str_p);
821/// }
822///
823/// // ACCESSORS
824///
825/// /// Return a pointer providing modifiable access to the allocator
826/// /// associated with this `String`.
827/// bslma::Allocator *allocator() const
828/// {
829/// return d_alloc_p;
830/// }
831/// };
832/// @endcode
833/// Next, we create a code fragment that will construct a managed `String`
834/// object using the default allocator to supply memory:
835/// @code
836/// void testInplaceCreation()
837/// {
838/// @endcode
839/// Suppose we want to have a different allocator supply memory allocated by the
840/// object:
841/// @code
842/// bslma::TestAllocator ta;
843/// bsls::Types::Int64 testBytesInUse = ta.numBytesInUse();
844///
845/// assert(0 == testBytesInUse);
846///
847/// bslma::TestAllocator da;
848/// bslma::DefaultAllocatorGuard dag(&da);
849/// bsls::Types::Int64 defaultBytesInUse = da.numBytesInUse();
850///
851/// assert(0 == defaultBytesInUse);
852/// @endcode
853/// Then, create a string to copy:
854/// @code
855/// const char *STR = "Test string";
856/// const int STR_LENGTH = static_cast<int>(std::strlen(STR));
857/// @endcode
858/// Next, dynamically create an object and obtain the managed pointer referring
859/// to it using the `bslma::ManagedPtrUtil::makeManaged` function:
860/// @code
861/// {
862/// bslma::ManagedPtr<String> stringManagedPtr =
863/// bslma::ManagedPtrUtil::makeManaged<String>(STR, &ta);
864/// @endcode
865/// Note that memory for the object itself is supplied by the default allocator,
866/// while memory for the copy of the passed string is supplied by another
867/// allocator:
868/// @code
869/// assert(static_cast<int>(sizeof(String)) <= da.numBytesInUse());
870/// assert(&ta == stringManagedPtr->allocator());
871/// assert(STR_LENGTH + 1 == ta.numBytesInUse());
872/// }
873/// @endcode
874/// Then, make sure that all allocated memory is successfully released after
875/// managed pointer destruction:
876/// @code
877/// assert(0 == da.numBytesInUse());
878/// assert(0 == ta.numBytesInUse());
879/// @endcode
880/// If you want to use an allocator other than the default allocator, then the
881/// `allocateManaged` function should be used instead:
882/// @code
883/// bslma::TestAllocator oa;
884/// bsls::Types::Int64 objectBytesInUse = oa.numBytesInUse();
885/// assert(0 == objectBytesInUse);
886///
887/// {
888/// bslma::ManagedPtr<String> stringManagedPtr =
889/// bslma::ManagedPtrUtil::allocateManaged<String>(&oa, STR, &ta);
890///
891/// assert(static_cast<int>(sizeof(String)) <= oa.numBytesInUse());
892/// assert(&ta == stringManagedPtr->allocator());
893/// assert(STR_LENGTH + 1 == ta.numBytesInUse());
894/// assert(0 == da.numBytesInUse());
895/// }
896///
897/// assert(0 == da.numBytesInUse());
898/// assert(0 == ta.numBytesInUse());
899/// assert(0 == oa.numBytesInUse());
900/// }
901/// @endcode
902/// Next, let's look at a more common scenario where the object's type uses
903/// `bslma` allocators. In that case `allocateManaged` implicitly passes the
904/// supplied allocator to the object's constructor as an extra argument in the
905/// final position.
906///
907/// The second example class almost completely repeats the first one, except
908/// that it explicitly defines the `bslma::UsesBslmaAllocator` trait:
909/// @code
910/// // Simple class that stores a copy of a null-terminated C-style string
911/// // and explicitly claims to use `bslma` allocators.
912/// class StringAlloc {
913///
914/// private:
915/// // DATA
916/// char *d_str_p; // stored value (owned)
917/// bslma::Allocator *d_alloc_p; // allocator to allocate any dynamic
918/// // memory (held, not owned)
919///
920/// public:
921/// // TRAITS
922/// BSLMF_NESTED_TRAIT_DECLARATION(StringAlloc, bslma::UsesBslmaAllocator);
923///
924/// // CREATORS
925///
926/// /// Create an object having the same value as the specified `str`.
927/// /// Optionally specify a `basicAllocator` used to supply memory. If
928/// /// `basicAllocator` is 0, the currently installed default allocator
929/// /// is used.
930/// StringAlloc(const char *str, bslma::Allocator *basicAllocator = 0)
931/// : d_alloc_p(bslma::Default::allocator(basicAllocator))
932/// {
933/// assert(str);
934///
935/// std::size_t length = std::strlen(str);
936///
937/// d_str_p = static_cast<char *>(d_alloc_p->allocate(length + 1));
938/// std::memcpy(d_str_p, str, length + 1);
939/// }
940///
941/// /// Destroy this object.
942/// ~StringAlloc()
943/// {
944/// d_alloc_p->deallocate(d_str_p);
945/// }
946///
947/// // ACCESSORS
948///
949/// /// Return a pointer providing modifiable access to the allocator
950/// /// associated with this `StringAlloc`.
951/// bslma::Allocator *allocator() const
952/// {
953/// return d_alloc_p;
954/// }
955/// };
956/// @endcode
957/// Then, let's create two managed objects using both `makeManaged` and
958/// `allocateManaged`:
959/// @code
960/// void testUsesAllocatorInplaceCreation()
961/// {
962/// bslma::TestAllocator ta;
963/// bsls::Types::Int64 testBytesInUse = ta.numBytesInUse();
964///
965/// assert(0 == testBytesInUse);
966///
967/// bslma::TestAllocator da;
968/// bslma::DefaultAllocatorGuard dag(&da);
969/// bsls::Types::Int64 defaultBytesInUse = da.numBytesInUse();
970///
971/// assert(0 == defaultBytesInUse);
972///
973/// const char *STR = "Test string";
974/// const int STR_LENGTH = static_cast<int>(std::strlen(STR));
975///
976/// @endcode
977/// Note that we need to explicitly supply the allocator's address to
978/// `makeManaged` to be passed to the object's constructor:
979/// @code
980/// {
981/// bslma::ManagedPtr<StringAlloc> stringManagedPtr =
982/// bslma::ManagedPtrUtil::makeManaged<StringAlloc>(STR, &ta);
983///
984/// assert(static_cast<int>(sizeof(String)) <= da.numBytesInUse());
985/// assert(&ta == stringManagedPtr->allocator());
986/// assert(STR_LENGTH + 1 == ta.numBytesInUse());
987/// }
988///
989/// @endcode
990/// But the supplied allocator is implicitly passed to the constructor by
991/// `allocateManaged`:
992/// @code
993/// {
994/// bslma::ManagedPtr<StringAlloc> stringManagedPtr =
995/// bslma::ManagedPtrUtil::allocateManaged<StringAlloc>(&ta, STR);
996///
997/// assert(static_cast<int>(sizeof(String)) + STR_LENGTH + 1 <=
998/// ta.numBytesInUse());
999/// assert(&ta == stringManagedPtr->allocator());
1000/// assert(0 == da.numBytesInUse());
1001/// }
1002/// @endcode
1003/// Finally, make sure that all allocated memory is successfully released after
1004/// the managed pointers (and the objects they manage) are destroyed:
1005/// @code
1006/// assert(0 == da.numBytesInUse());
1007/// assert(0 == ta.numBytesInUse());
1008/// }
1009/// @endcode
1010/// @}
1011/** @} */
1012/** @} */
1013
1014/** @addtogroup bsl
1015 * @{
1016 */
1017/** @addtogroup bslma
1018 * @{
1019 */
1020/** @addtogroup bslma_managedptr
1021 * @{
1022 */
1023
1024#include <bslscm_version.h>
1025
1026#include <bslma_allocator.h>
1027#include <bslma_constructionutil.h>
1029#include <bslma_default.h>
1033#include <bslma_pointerutil.h>
1035
1036#include <bslmf_addreference.h>
1037#include <bslmf_assert.h>
1038#include <bslmf_conditional.h>
1039#include <bslmf_enableif.h>
1042#include <bslmf_isclass.h>
1043#include <bslmf_isconvertible.h>
1045#include <bslmf_isvoid.h>
1046#include <bslmf_movableref.h>
1047#include <bslmf_removecv.h>
1048#include <bslmf_util.h> // 'forward(V)' for C++03
1049
1050#include <bsls_assert.h>
1051#include <bsls_compilerfeatures.h>
1052#include <bsls_keyword.h>
1053#include <bsls_nullptr.h>
1054#include <bsls_platform.h>
1055#include <bsls_unspecifiedbool.h>
1056#include <bsls_util.h> // 'forward<T>(V)' for C++11
1057
1058#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1059// clang-format off
1060// Include version that can be compiled with C++03
1061// Generated on Mon Jan 13 08:31:27 2025
1062// Command line: sim_cpp11_features.pl bslma_managedptr.h
1063
1064# define COMPILING_BSLMA_MANAGEDPTR_H
1065# include <bslma_managedptr_cpp03.h>
1066# undef COMPILING_BSLMA_MANAGEDPTR_H
1067
1068// clang-format on
1069#else
1070
1071
1072namespace bslma {
1073
1074 // ============================
1075 // private class ManagedPtr_Ref
1076 // ============================
1077
1078/// This class holds a managed pointer reference, returned by the implicit
1079/// conversion operator in the class `ManagedPtr`. This class is used to
1080/// allow the construction of managed pointers from temporary managed
1081/// pointer objects, since temporaries cannot bind to the reference to a
1082/// modifiable object used in the copy constructor and copy-assignment operator for `ManagedPtr`.
1083///
1084/// \note Note that while no members or methods of
1085/// this class template depend on the specified `TARGET_TYPE`, it is
1086/// important to carry this type into conversions to support passing
1087/// ownership of `ManagedPtr_Members` pointers when assigning or
1088/// constructing `ManagedPtr` objects.
1089///
1090/// See @ref bslma_managedptr
1091template <class TARGET_TYPE>
1093
1094 // DATA
1095 ManagedPtr_Members *d_base_p; // non-null pointer to the managed state of
1096 // a 'ManagedPtr' object
1097
1098 TARGET_TYPE *d_cast_p; // safely-cast pointer to the referenced
1099 // object
1100
1101 public:
1102 // CREATORS
1103
1104 /// Create a `ManagedPtr_Ref` object having the specified `base` value
1105 /// for its `base` attribute, and the specified `target` for its `target` attribute.
1106 ///
1107 /// \note Note that `target` (but not `base`) may be
1108 /// null.
1110
1111 ManagedPtr_Ref(const ManagedPtr_Ref& original) = default;
1112 // Create a 'ManagedPtr_Ref' object having the same 'd_base_p' value as
1113 // the specified 'original'. Note that this trivial constructor's
1114 // definition is compiler generated.
1115
1116 /// Destroy this object.
1117 /// \note Note that the referenced managed object is
1118 /// *not* destroyed.
1120
1121 // MANIPULATORS
1122 ManagedPtr_Ref& operator=(const ManagedPtr_Ref& original) = default;
1123 // Create a 'ManagedPtr_Ref' object having the same 'd_base_p' as the
1124 // specified 'original'. Note that this trivial copy-assignment
1125 // operator's definition is compiler generated.
1126
1127 // ACCESSORS
1128
1129 /// Return a pointer to the managed state of a `ManagedPtr` object.
1130 ManagedPtr_Members *base() const;
1131
1132 /// Return a pointer to the referenced object.
1133 TARGET_TYPE *target() const;
1134};
1135
1136 // =========================================
1137 // private struct ManagedPtr_TraitConstraint
1138 // =========================================
1139
1140/// This `struct` is an empty type that exists solely to enable constructor
1141/// access to be constrained by type trait.
1142///
1143/// See @ref bslma_managedptr
1146 // ================
1147 // class ManagedPtr
1148 // ================
1149
1150/// This class is a "smart pointer" that refers to a *target* object
1151/// accessed via a pointer to the specified parameter type, `TARGET_TYPE`,
1152/// and that supports sole ownership of a *managed* object that is
1153/// potentially of a different type, and may be an entirely different object
1154/// from the target object. A managed pointer ensures that the object it
1155/// manages is destroyed when the managed pointer is destroyed (or
1156/// re-assigned), using the "deleter" supplied along with the managed
1157/// object. The target object referenced by a managed pointer may be
1158/// accessed using either the `->` operator, or the dereference operator
1159/// (`operator *`). The specified `TARGET_TYPE` may be `const`-qualified,
1160/// but may not be `volatile`-qualified, nor may it be a reference type.
1161///
1162/// A managed pointer may be *empty*, in which case it neither refers to a
1163/// target object nor owns a managed object. An empty managed pointer is
1164/// the equivalent of a null pointer: Such a managed pointer is not
1165/// de-referenceable, and tests as `false` in boolean expressions.
1166///
1167/// A managed pointer for which the managed object is not the same object as
1168/// the target is said to *alias* the managed object (see the section
1169/// "Aliasing" in the component-level documentation).
1170///
1171/// See @ref bslma_managedptr
1172template <class TARGET_TYPE>
1174
1175 public:
1176 // INTERFACE TYPES
1177
1178 /// Alias for a function-pointer type for functions used to destroy the
1179 /// object managed by a `ManagedPtr` object.
1181
1182 /// Alias to the `TARGET_TYPE` template parameter.
1183 typedef TARGET_TYPE element_type;
1184
1185 private:
1186 // PRIVATE TYPES
1187
1188 /// `BoolType` is an alias for an unspecified type that is implicitly
1189 /// convertible to `bool`, but will not promote to `int`. This (opaque)
1190 /// type can be used as an "unspecified boolean type" for converting a
1191 /// managed pointer to `bool` in contexts such as `if (mp) { ... }`
1192 /// without actually having a conversion to `bool` or being less-than
1193 /// comparable (either of which would also enable undesirable implicit
1194 /// comparisons of managed pointers to `int` and less-than comparisons).
1195 typedef typename bsls::UnspecifiedBool<ManagedPtr>::BoolType BoolType;
1196
1197 /// This `typedef` is a convenient alias for the utility associated with
1198 /// movable references.
1200
1201 // DATA
1202 ManagedPtr_Members d_members; // state managed by this object
1203
1204 // PRIVATE CLASS METHODS
1205
1206 /// Return the value of the specified `ptr` as a `void *`, after
1207 /// stripping all `const` and `volatile` qualifiers from `TARGET_TYPE`.
1208 /// This function avoids accidental type-safety errors when performing the necessary sequence of casts.
1209 ///
1210 /// \note Note that calling this function
1211 /// implies a conversion of the calling pointer to `TARGET_TYPE *`,
1212 /// which, in rare cases, may involve some adjustment of the pointer
1213 /// value, e.g., in the case of multiple inheritance where `TARGET_TYPE`
1214 /// is not a left-most base of the complete object type.
1215 static void *stripBasePointerType(TARGET_TYPE *ptr);
1216
1217 /// Return the value of the specified `ptr` as a `void *`, after
1218 /// stripping all `const` and `volatile` qualifiers from `MANAGED_TYPE`.
1219 /// This function avoids accidental type-safety errors when performing
1220 /// the necessary sequence of casts.
1221 template <class MANAGED_TYPE>
1222 static void *stripCompletePointerType(MANAGED_TYPE *ptr);
1223
1224 // PRIVATE MANIPULATORS
1225
1226 /// Destroy the currently managed object, if any. Then, set the target
1227 /// object of this managed pointer to be that referenced by the
1228 /// specified `ptr`, take ownership of `*ptr` as the currently managed
1229 /// object, and set a deleter that will invoke the specified `deleter`
1230 /// with the address of the currently managed object, and with the
1231 /// specified `cookie` (that the deleter can use for its own purposes),
1232 /// unless `0 == ptr`, in which case reset this managed pointer to empty.
1233 ///
1234 /// \pre The behavior is undefined if `ptr` is already managed by
1235 /// another object, or if `0 == deleter && 0 != ptr`.
1236 template <class MANAGED_TYPE>
1237 void loadImp(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1238
1239 private:
1240 // NOT IMPLEMENTED
1241
1242 /// It is never defined behavior to pass a null pointer literal as a
1243 /// factory, unless the specified `ptr` is also a null pointer literal.
1244 template <class MANAGED_TYPE>
1245 ManagedPtr(MANAGED_TYPE *, bsl::nullptr_t);
1246
1247 private:
1248 // NOT IMPLEMENTED
1249
1250 /// It is never defined behavior to pass a null literal as a deleter,
1251 /// unless the `object` pointer is also a null pointer literal.
1252 template <class MANAGED_TYPE, class COOKIE_TYPE>
1253 ManagedPtr(MANAGED_TYPE *, COOKIE_TYPE *, bsl::nullptr_t);
1254
1255 private:
1256 // NOT IMPLEMENTED
1257
1258 /// It is never defined behavior to pass a null literal as a deleter,
1259 /// unless the `object` pointer is also a null pointer literal.
1260 template <class MANAGED_TYPE>
1261 void load(MANAGED_TYPE *, bsl::nullptr_t, bsl::nullptr_t);
1262 template <class COOKIE_TYPE>
1263 void load(TARGET_TYPE *, COOKIE_TYPE *, bsl::nullptr_t);
1264
1265 private:
1266 // NOT IMPLEMENTED
1267
1268 /// These two operator overloads are declared as `private` but never
1269 /// defined in order to eliminate accidental equality comparisons that
1270 /// would occur through the implicit conversion to `BoolType`.
1271 ///
1272 /// \note Note that the return type of `void` is chosen as it will often produce a
1273 /// clearer error message than relying on the `private` control failure.
1274 /// Also note that these private operators will not be needed with
1275 /// C++11, where an `explicit operator bool()` conversion operator would
1276 /// be preferred.
1277 void operator==(const ManagedPtr&) const;
1278 void operator!=(const ManagedPtr&) const;
1279
1280 // FRIENDS
1281 template <class ALIASED_TYPE>
1282 friend class ManagedPtr; // required only for alias support
1283
1284 public:
1285 // CREATORS
1286
1287 /// Create an empty managed pointer.
1290
1291 /// Create a managed pointer having a target object referenced by the
1292 /// specified `ptr`, owning the managed object `*ptr`, and having a
1293 /// deleter that will call `delete ptr` to destroy the managed object
1294 /// when invoked (e.g., when this managed pointer object is destroyed),
1295 /// unless `0 == ptr`, in which case create an empty managed pointer.
1296 /// The deleter will invoke the destructor of `MANAGED_TYPE` rather than
1297 /// the destructor of `TARGET_TYPE`. This constructor will not compile
1298 /// unless `MANAGED_TYPE *` is convertible to `TARGET_TYPE *`.
1299 ///
1300 /// \note Note that this behavior allows `ManagedPtr` to be defined for `void`
1301 /// pointers, and to call the correct destructor for the managed object,
1302 /// even if the destructor for `TARGET_TYPE` is not declared as `virtual`.
1303 ///
1304 /// \pre The behavior is undefined unless the managed object (if
1305 /// any) can be destroyed by `delete`, or if the lifetime of the managed
1306 /// object is already managed by another object.
1307 template <class MANAGED_TYPE>
1308 explicit ManagedPtr(MANAGED_TYPE *ptr);
1309
1310 /// Create a managed pointer having the same target object as the
1311 /// managed pointer referenced by the specified `ref`, transfer
1312 /// ownership of the managed object owned by the managed pointer
1313 /// referenced by `ref`, and reset the managed pointer referenced by
1314 /// `ref` to empty. This constructor is used to create a managed
1315 /// pointer from a managed pointer rvalue, or from a managed pointer to
1316 /// a "compatible" type, where "compatible" means a built-in conversion
1317 /// from `COMPATIBLE_TYPE *` to `TARGET_TYPE *` is defined, e.g.,
1318 /// `derived *` to `base *`, `T *` to `const T *`, or `T *` to `void *`.
1320 BSLS_KEYWORD_NOEXCEPT; // IMPLICIT
1321
1323
1324 /// Create a managed pointer having the same target object as the
1325 /// specified `original`, transfer ownership of the object managed by
1326 /// `original` (if any) to this managed pointer, and reset `original` to
1327 /// empty.
1329
1330 /// Create a managed pointer having the same target object as the specified
1331 /// `original`, transfer ownership of the object managed by `original` (if
1332 /// any) to this managed pointer, and reset `original` to empty.
1333 /// `TARGET_TYPE` must be an accessible and unambiguous base of
1334 /// `BDE_OTHER_TYPE`
1335#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1336 template <class BDE_OTHER_TYPE>
1338 typename bsl::enable_if<
1343#elif defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
1344 // sun compiler version 12.3 and earlier
1345 template <class BDE_OTHER_TYPE>
1348#else // c++03 except old (version <= 12.3) sun compilers
1349 template <class BDE_OTHER_TYPE>
1351 typename bsl::enable_if<
1356#endif
1357
1358 /// Create a managed pointer that takes ownership of the object managed
1359 /// by the specified `alias`, but which uses the specified `ptr` to
1360 /// refer to its target object, unless `0 == ptr`, in which case create
1361 /// an empty managed pointer. Reset `alias` to empty if ownership of its managed object is transferred.
1362 ///
1363 /// \pre The behavior is undefined if `alias` is empty, but `0 != ptr`.
1364 ///
1365 /// \note Note that destroying or
1366 /// re-assigning a managed pointer created with this constructor will
1367 /// destroy the object originally managed by `alias` (unless `release`
1368 /// is called first); the destructor for `*ptr` is not called directly.
1369 template <class ALIASED_TYPE>
1371 template <class ALIASED_TYPE>
1372#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1374#else
1376#endif
1377 TARGET_TYPE *ptr);
1378
1379 /// Create a managed pointer having a target object referenced by the
1380 /// specified `ptr`, owning the managed object `*ptr`, and having a
1381 /// deleter that will call `factory->deleteObject(ptr)` to destroy the
1382 /// managed object when invoked (e.g., when this managed pointer object
1383 /// is destroyed), unless `0 == ptr`, in which case create an empty
1384 /// managed pointer. The deleter will invoke the destructor of
1385 /// `MANAGED_TYPE` rather than the destructor of `TARGET_TYPE`. This
1386 /// constructor will not compile unless `MANAGED_TYPE *` is convertible to `TARGET_TYPE *`.
1387 ///
1388 /// \pre The behavior is undefined unless the managed
1389 /// object (if any) can be destroyed by the specified `factory`, or if
1390 /// `0 == factory && 0 != ptr`, or if the lifetime of the managed object is already managed by another object.
1391 ///
1392 /// \note Note that `bslma::Allocator`,
1393 /// and any class publicly and unambiguously derived from
1394 /// `bslma::Allocator`, meets the requirements for `FACTORY_TYPE`.
1395 template <class MANAGED_TYPE, class FACTORY_TYPE>
1396 ManagedPtr(MANAGED_TYPE *ptr, FACTORY_TYPE *factory);
1397
1398 /// Create an empty managed pointer.
1399 /// \note Note that this constructor is
1400 /// necessary to match null-pointer literal arguments, in order to break
1401 /// ambiguities and provide valid type deduction with the other
1402 /// constructor templates in this class.
1404
1405 /// Create an empty managed pointer.
1406 /// \note Note that the specified `factory`
1407 /// is ignored, as an empty managed pointer does not call its deleter.
1408 template <class FACTORY_TYPE>
1409 ManagedPtr(bsl::nullptr_t, FACTORY_TYPE *factory);
1410
1411 /// Create a managed pointer having a target object referenced by the
1412 /// specified `ptr`, owning the managed object `*ptr`, and having a
1413 /// deleter that will invoke the specified `deleter` with the address of
1414 /// the currently managed object, and with the specified `cookie` (that
1415 /// the deleter can use for its own purposes), unless `0 == ptr`, in
1416 /// which case create an empty managed pointer.
1417 ///
1418 /// \pre The behavior is undefined if `ptr` is already managed by another object, or if `0 == deleter && 0 != ptr`.
1419 ///
1420 /// \note Note that this constructor is required
1421 /// only because the deprecated overloads cause an ambiguity in its
1422 /// absence; it should be removed when the deprecated overloads are
1423 /// removed.
1424 ManagedPtr(TARGET_TYPE *ptr, void *cookie, DeleterFunc deleter);
1425
1426 /// Create a managed pointer having a target object referenced by the
1427 /// specified `ptr`, owning the managed object `*ptr`, and having a
1428 /// deleter that will invoke the specified `deleter` with the address of
1429 /// the currently managed object, and with the specified `cookie` (that
1430 /// the deleter can use for its own purposes), unless `0 == ptr`, in
1431 /// which case create an empty managed pointer. This constructor will
1432 /// not compile unless `MANAGED_TYPE *` is convertible to
1433 /// `TARGET_TYPE *`. The deleter will invoke the destructor of
1434 /// `MANAGED_TYPE` rather than the destructor of `TARGET_TYPE`.
1435 ///
1436 /// \pre The behavior is undefined if `ptr` is already managed by another object,
1437 /// or if `0 == deleter && 0 != ptr`.
1438 template <class MANAGED_TYPE>
1439 ManagedPtr(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1440
1441#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1442 /// Create a managed pointer having a target object referenced by the
1443 /// specified `ptr`, owning the managed object `*ptr`, and having a
1444 /// deleter that will invoke the specified `deleter` with the address of
1445 /// the currently managed object, and with the specified `cookie` (that
1446 /// the deleter can use for its own purposes), unless `0 == ptr`, in
1447 /// which case create an empty managed pointer. This constructor will
1448 /// not compile unless `MANAGED_TYPE *` is convertible to
1449 /// `TARGET_TYPE *`, and `MANAGED_TYPE *` is convertible to
1450 /// `MANAGED_BASE *`. The deleter will invoke the destructor of
1451 /// `MANAGED_TYPE` rather than the destructor of `TARGET_TYPE`.
1452 ///
1453 /// \pre The behavior is undefined if `ptr` is already managed by another object, or if `0 == deleter && 0 != ptr`.
1454 ///
1455 /// \note Note that this constructor is
1456 /// needed only to avoid ambiguous type deductions when passing a null
1457 /// pointer literal as the `cookie` when the user passes a deleter
1458 /// taking a type other than `void *` for its object type. Also note
1459 /// that this function is *deprecated* as it relies on undefined
1460 /// compiler behavior for its implementation (that luckily performs as
1461 /// required on every platform supported by BDE).
1462 ///
1463 /// @deprecated Instead, use:
1464 /// @code
1465 /// template <class MANAGED_TYPE>
1466 /// ManagedPtr(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1467 /// @endcode
1468 template <class MANAGED_TYPE, class MANAGED_BASE>
1469 ManagedPtr(MANAGED_TYPE *ptr,
1470 void *cookie,
1471 void (*deleter)(MANAGED_BASE *, void *));
1472
1473 /// Create a managed pointer having a target object referenced by the
1474 /// specified `ptr`, owning the managed object `*ptr`, and having a
1475 /// deleter that will invoke the specified `deleter` with the address of
1476 /// the currently managed object, and with the specified `cookie` (that
1477 /// the deleter can use for its own purposes), unless `0 == ptr`, in
1478 /// which case create an empty managed pointer. This constructor will
1479 /// not compile unless `MANAGED_TYPE *` is convertible to
1480 /// `TARGET_TYPE *`, and `MANAGED_TYPE *` is convertible to
1481 /// `MANAGED_BASE *`. The deleter will invoke the destructor of
1482 /// `MANAGED_TYPE` rather than the destructor of `TARGET_TYPE`.
1483 ///
1484 /// \pre The behavior is undefined if `ptr` is already managed by another object, or if `0 == deleter && 0 != ptr`.
1485 ///
1486 /// \note Note that this function is
1487 /// *deprecated* as it relies on undefined compiler behavior for its
1488 /// implementation (that luckily performs as required on every platform
1489 /// supported by BDE).
1490 ///
1491 /// @deprecated Instead, use:
1492 /// @code
1493 /// template <class MANAGED_TYPE>
1494 /// ManagedPtr(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1495 /// @endcode
1496 template <class MANAGED_TYPE,
1497 class MANAGED_BASE,
1498 class COOKIE_TYPE,
1499 class COOKIE_BASE>
1500 ManagedPtr(MANAGED_TYPE *ptr,
1501 COOKIE_TYPE *cookie,
1502 void (*deleter)(MANAGED_BASE *, COOKIE_BASE *));
1503#endif // BDE_OMIT_INTERNAL_DEPRECATED
1504
1505 /// Destroy this managed pointer object. Destroy the object managed by
1506 /// this managed pointer by invoking the user-supplied deleter, unless
1507 /// this managed pointer is empty, in which case the deleter will *not*
1508 /// be called.
1510
1511 // MANIPULATORS
1513
1514 /// If this object and the specified `rhs` manage the same object,
1515 /// return a reference to this managed pointer; otherwise, destroy the
1516 /// managed object owned by this managed pointer, transfer ownership of
1517 /// the managed object owned by `rhs` to this managed pointer, set this
1518 /// managed pointer to point to the target object referenced by `rhs`,
1519 /// reset `rhs` to empty, and return a reference to this managed
1520 /// pointer.
1523
1524 /// If this object and the specified `rhs` manage the same object,
1525 /// return a reference to this managed pointer; otherwise, destroy the
1526 /// managed object owned by this managed pointer, transfer ownership of
1527 /// the managed object owned by `rhs` to this managed pointer, set this
1528 /// managed pointer to point to the target object referenced by `rhs`,
1529 /// reset `rhs` to empty, and return a reference to this managed
1530 /// pointer. `TARGET_TYPE` must be an accessible and unambiguous base
1531 /// of `BDE_OTHER_TYPE`
1532#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1533 template <class BDE_OTHER_TYPE>
1534 typename bsl::enable_if<
1538#elif defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
1539 // sun compiler version 12.3 and earlier
1540 template <class BDE_OTHER_TYPE>
1544#else // c++03 except old (version <= 12.3) sun compilers
1545 template <class BDE_OTHER_TYPE>
1546 typename bsl::enable_if<
1551#endif
1552
1553 /// If this object and the managed pointer reference by the specified
1554 /// `ref` manage the same object, return a reference to this managed
1555 /// pointer; otherwise, destroy the managed object owned by this managed
1556 /// pointer, transfer ownership of the managed object owned by the
1557 /// managed pointer referenced by `ref`, and set this managed pointer to
1558 /// point to the target object currently referenced the managed pointer
1559 /// referenced by `ref`; then reset the managed pointer referenced by
1560 /// `ref` to empty, and return a reference to this managed pointer.
1561 /// This operator is (implicitly) used to assign from a managed pointer
1562 /// rvalue, or from a managed pointer to a "compatible" type, where
1563 /// "compatible" means a built-in conversion from `MANAGED_TYPE *` to
1564 /// `TARGET_TYPE *` is defined, e.g., `derived *` to `base *`, `T *` to
1565 /// `const T *`, or `T *` to `void *`.
1568
1569 /// Destroy the current managed object (if any) and reset this managed
1570 /// pointer to empty.
1572
1573 /// Return a managed pointer reference, referring to this object.
1574 ///
1575 /// \note Note that this conversion operator is used implicitly to allow the
1576 /// construction of managed pointers from rvalues because temporaries
1577 /// cannot be passed by references offering modifiable access.
1578 template <class REFERENCED_TYPE>
1580
1581 /// Destroy the current managed object (if any) and reset this managed
1582 /// pointer to empty.
1583 ///
1584 /// @deprecated Use @ref reset instead.
1585 void clear();
1586
1587 /// Destroy the currently managed object, if any. Then, set the target
1588 /// object of this managed pointer to be that referenced by the
1589 /// specified `ptr`, take ownership of `*ptr` as the currently managed
1590 /// object, and set a deleter that uses the currently installed default
1591 /// allocator to destroy the managed object when invoked (e.g., when
1592 /// this managed pointer object is destroyed), unless `0 == ptr`, in
1593 /// which case reset this managed pointer to empty. The deleter will
1594 /// invoke the destructor of `MANAGED_TYPE` rather than the destructor
1595 /// of `TARGET_TYPE`. This function will not compile unless
1596 /// `MANAGED_TYPE *` is convertible to `TARGET_TYPE *`.
1597 ///
1598 /// \pre The behavior is undefined unless the managed object (if any) can be destroyed by the
1599 /// currently installed default allocator, or if the lifetime of the
1600 /// managed object is already managed by another object.
1601 template <class MANAGED_TYPE>
1602 void load(MANAGED_TYPE *ptr);
1603
1604 /// Destroy the currently managed object, if any. Then, set the target
1605 /// object of this managed pointer to be that referenced by the
1606 /// specified `ptr`, take ownership of `*ptr` as the currently managed
1607 /// object, and set a deleter that calls `factory->deleteObject(ptr)` to
1608 /// destroy the managed object when invoked (e.g., when this managed
1609 /// pointer object is destroyed), unless `0 == ptr`, in which case reset
1610 /// this managed pointer to empty. The deleter will invoke the
1611 /// destructor of `MANAGED_TYPE` rather than the destructor of
1612 /// `TARGET_TYPE`. This function will not compile unless
1613 /// `MANAGED_TYPE *` is convertible to `TARGET_TYPE *`.
1614 ///
1615 /// \pre The behavior is undefined unless the managed object (if any) can be destroyed by the
1616 /// specified `factory`, or if `0 == factory && 0 != ptr`, or if the
1617 /// the lifetime of the managed object is already managed by another object.
1618 ///
1619 /// \note Note that `bslma::Allocator`, and any class publicly and
1620 /// unambiguously derived from `bslma::Allocator`, meets the
1621 /// requirements for `FACTORY_TYPE`.
1622 template <class MANAGED_TYPE, class FACTORY_TYPE>
1623 void load(MANAGED_TYPE *ptr, FACTORY_TYPE *factory);
1624
1625 /// Destroy the currently managed object, if any. Then, set the target
1626 /// object of this managed pointer to be that referenced by the
1627 /// specified `ptr`, take ownership of `*ptr` as the currently managed
1628 /// object, and set a deleter that will invoke the specified `deleter`
1629 /// with the address of the currently managed object, and with the
1630 /// specified `cookie` (that the deleter can use for its own purposes),
1631 /// unless `0 == ptr`, in which case reset this managed pointer to empty.
1632 ///
1633 /// \pre The behavior is undefined if `ptr` is already managed by another object, or if `0 == deleter && 0 != ptr`.
1634 ///
1635 /// \note Note that GCC 3.4
1636 /// and earlier versions have a bug in template type deduction/overload
1637 /// resolution that causes ambiguities if this signature is available.
1638 /// This function will be restored on that platform once the deprecated
1639 /// signatures are finally removed.
1640 template <class MANAGED_TYPE>
1641 void load(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1642
1643 /// Destroy the current managed object (if any) and reset this managed pointer to empty.
1644 ///
1645 /// \note Note that the optionally specified `cookie` and
1646 /// `deleter` will be ignored, as empty managed pointers do not invoke a
1647 /// deleter.
1648 void load(bsl::nullptr_t = 0, void *cookie = 0, DeleterFunc deleter = 0);
1649
1650#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1651 template <class MANAGED_TYPE, class COOKIE_TYPE>
1652 void load(MANAGED_TYPE *ptr, COOKIE_TYPE *cookie, DeleterFunc deleter);
1653
1654 template <class MANAGED_TYPE, class MANAGED_BASE>
1655 void load(MANAGED_TYPE *ptr,
1656 void *cookie,
1657 void (*deleter)(MANAGED_BASE *, void *));
1658
1659 /// Destroy the currently managed object, if any. Then, set the target
1660 /// object of this managed pointer to be that referenced by the
1661 /// specified `ptr`, take ownership of `*ptr` as the currently managed
1662 /// object, and set a deleter that will invoke the specified `deleter`
1663 /// with the address of the currently managed object, and with the
1664 /// specified `cookie` (that the deleter can use for its own purposes),
1665 /// unless `0 == ptr`, in which case reset this managed pointer to empty.
1666 ///
1667 /// \pre The behavior is undefined if `ptr` is already managed by another object, or if `0 == deleter && 0 != ptr`.
1668 ///
1669 /// \note Note that this
1670 /// function is *deprecated* as it relies on undefined compiler behavior
1671 /// for its implementation, but luckily perform as required for all
1672 /// currently supported platforms; on platforms where the non-deprecated
1673 /// overload is not available (e.g., GCC 3.4) code should be written as
1674 /// if it were available, as an appropriate (deprecated) overload will
1675 /// be selected with the correct (non-deprecated) behavior.
1676 ///
1677 /// @deprecated Instead, use:
1678 /// @code
1679 /// template <class MANAGED_TYPE>
1680 /// void load(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1681 /// @endcode
1682 template <class MANAGED_TYPE,
1683 class MANAGED_BASE,
1684 class COOKIE_TYPE,
1685 class COOKIE_BASE>
1686 void load(MANAGED_TYPE *ptr,
1687 COOKIE_TYPE *cookie,
1688 void (*deleter)(MANAGED_BASE *, COOKIE_BASE *));
1689#endif // BDE_OMIT_INTERNAL_DEPRECATED
1690
1691 /// If the specified `alias` manages the same object as this managed
1692 /// pointer, set the target object of this managed pointer to be that
1693 /// referenced by the specified `ptr`; otherwise, destroy the currently
1694 /// managed object (if any), and if `alias` is empty, reset this managed
1695 /// pointer to empty; otherwise, transfer ownership (and the deleter) of
1696 /// the object managed by `alias`, and set the target object of this
1697 /// managed pointer to be that referenced by `ptr`.
1698 ///
1699 /// \pre The behavior is undefined if `0 == ptr` and `alias` is not empty, or if `0 != ptr`
1700 /// and `alias` is empty, or if `ptr` is already managed by a managed pointer other than `alias`.
1701 ///
1702 /// \note Note that this establishes a managed
1703 /// pointer where `ptr` aliases `alias`. The managed object for `alias`
1704 /// will ultimately be destroyed, and the destructor for `ptr` is not
1705 /// called directly.
1706 template <class ALIASED_TYPE>
1707 void loadAlias(ManagedPtr<ALIASED_TYPE>& alias, TARGET_TYPE *ptr);
1708
1709 /// Return a raw pointer to the current target object (if any) and the
1710 /// deleter for the currently managed object, and reset this managed
1711 /// pointer to empty. It is undefined behavior to run the returned
1712 /// deleter unless the returned pointer to target object is not null.
1714
1715 /// Load the specified `deleter` for the currently managed object and
1716 /// reset this managed pointer to empty. Return a raw pointer to the
1717 /// target object (if any) managed by this pointer. It is undefined
1718 /// behavior to run the returned deleter unless the returned pointer to
1719 /// target object is not null.
1721
1722 /// Destroy the current managed object (if any) and reset this managed
1723 /// pointer to empty.
1724 void reset();
1725
1726 /// Exchange the value and ownership of this managed pointer with the
1727 /// specified `other` managed pointer.
1728 void swap(ManagedPtr& other);
1729
1730 // ACCESSORS
1731
1732 /// Return `true` if this managed pointer is empty, and `false` otherwise.
1734
1735 /// Return `false` if this managed pointer is empty, and `true` otherwise.
1737
1738 /// Return a value of "unspecified bool" type that evaluates to `false`
1739 /// if this managed pointer is empty, and `true` otherwise.
1740 ///
1741 /// \note Note that this conversion operator allows a managed pointer to be used within
1742 /// a conditional context, such as within an `if` or `while` statement,
1743 /// but does *not* allow managed pointers to be compared (e.g., via `<`
1744 /// or `>`). Also note that a superior solution is available in C++11
1745 /// using the `explicit operator bool()` syntax, that removes the need
1746 /// for a special boolean-like type and private equality-comparison
1747 /// operators.
1748 operator BoolType() const;
1749
1750 /// Return a reference to the target object.
1751 ///
1752 /// \pre The behavior is undefined if this managed pointer is empty, or if `TARGET_TYPE` is `void` or
1753 /// `const void`.
1755
1756 /// Return the address of the target object, or 0 if this managed
1757 /// pointer is empty.
1758 TARGET_TYPE *operator->() const;
1759
1760 /// Return a reference to the non-modifiable deleter information associated with this managed pointer.
1761 ///
1762 /// \pre The behavior is undefined if
1763 /// this managed pointer is empty.
1765
1766 /// Return the address of the target object, or 0 if this managed
1767 /// pointer is empty.
1768 TARGET_TYPE *get() const;
1769
1770 /// Return the address of the target object, or 0 if this managed
1771 /// pointer is empty.
1772 ///
1773 /// @deprecated Use @ref get instead.
1774 TARGET_TYPE *ptr() const;
1775};
1776
1777// FREE FUNCTIONS
1778
1779/// Efficiently exchange the values of the specified `a` and `b` objects.
1780/// This function provides the no-throw exception-safety guarantee.
1781template <class TARGET_TYPE>
1783
1784 // =====================
1785 // struct ManagedPtrUtil
1786 // =====================
1787
1788/// This utility class provides a general no-op deleter, which is useful
1789/// when creating managed pointers to stack-allocated objects.
1790///
1791/// See @ref bslma_managedptr
1793
1794 // CLASS METHODS
1795
1796 /// Deleter function that does nothing.
1797 static void noOpDeleter(void *, void *);
1798
1799 /// Make use of `AllocatorUtil::deleteObject` to destroy and deallocate
1800 /// the specified `object` using the specified allocator.
1801 ///
1802 /// \pre The behavior is undefined unless `allocator` is an instance of `bslma::Allocator`
1803 /// that was used to supply memory for `object` and `object` points to an
1804 /// instance of `ELEMENT_TYPE` that is within its lifetime.
1805 template <class ELEMENT_TYPE>
1806 static void allocatorDeleter(void *object, void *allocator);
1807
1808#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=14
1809
1810 /// Create an object of the (template parameter) `ELEMENT_TYPE` from the
1811 /// specified `args...` arguments, and return a `ManagedPtr` to manage
1812 /// the new object. Use the specified `allocator` to supply memory for
1813 /// the footprint of the new object and implicitly pass `allocator` as
1814 /// the allocator argument to the `ELEMENT_TYPE` constructor if
1815 /// `bslma::UsesBslmaAllocator<ELEMENT_TYPE>::value` is `true`. If
1816 /// `allocator` is a null pointer, the currently installed default allocator is used.
1817 ///
1818 /// \note Note that compilation will fail unless
1819 /// `allocator` is convertible to either `bslma::Allocator *` or
1820 /// `bsl::allocator<>`.
1821 template <class ELEMENT_TYPE, class... ARGS>
1823 allocateManaged(bslma::Allocator *allocator, ARGS&&... args);
1824 template <class ELEMENT_TYPE, class ALLOCATOR, class... ARGS>
1827 allocateManaged(const ALLOCATOR& allocator, ARGS&&... args);
1828
1829 /// Create an object of the (template parameter) `ELEMENT_TYPE` from the
1830 /// specified `args...` arguments, and return a `ManagedPtr` to manage
1831 /// the new object. Use the currently installed default allocator to
1832 /// supply memory for the footprint of the new object but do *not*
1833 /// implicitly pass the default allocator as the allocator argument to
1834 /// its constructor even if
1835 /// `bslma::UsesBslmaAllocator<ELEMENT_TYPE>::value` is `true`.
1836 ///
1837 /// \note Note that an allocator may be included in `args`, but see
1838 /// `allocateManaged` for an alternative function that is better suited
1839 /// to creating managed pointers to objects of allocator-aware type.
1840 template <class ELEMENT_TYPE, class... ARGS>
1841 static ManagedPtr<ELEMENT_TYPE> makeManaged(ARGS&&... args);
1842
1843#endif
1844};
1845
1846 // ===========================
1847 // struct ManagedPtrNilDeleter
1848 // ===========================
1849
1850/// This utility class provides a general no-op deleter, which is useful
1851/// when creating managed pointers to stack-allocated objects.
1852///
1853/// \note Note that the non-template class `ManagedPtrUtil` should be used in preference to
1854/// this deprecated class, avoiding both template bloat and undefined
1855/// behavior.
1856///
1857/// @deprecated Use @ref ManagedPtrUtil::noOpDeleter instead.
1858///
1859/// See @ref bslma_managedptr
1860template <class TARGET_TYPE>
1862
1863 // CLASS METHODS
1864
1865 /// Deleter function that does nothing.
1866 static void deleter(void *, void *);
1867};
1868
1869 // ===========================================
1870 // private class ManagedPtr_FactoryDeleterType
1871 // ===========================================
1872
1873/// This metafunction class-template provides a means to compute the
1874/// preferred deleter function for a factory class for those methods of
1875/// `ManagedPtr` that supply only a factory, and no additional deleter
1876/// function. The intent is to use a common deleter function for all
1877/// allocators that implement the `bslma::Allocator` protocol, rather than
1878/// create a special deleter function based on the complete type of each
1879/// allocator, each doing the same thing (invoking the virtual function
1880/// `deleteObject`).
1881template <class TARGET_TYPE, class FACTORY_TYPE>
1884 bsl::is_convertible<FACTORY_TYPE *, Allocator *>::value,
1885 ManagedPtr_FactoryDeleter<TARGET_TYPE, Allocator>,
1886 ManagedPtr_FactoryDeleter<TARGET_TYPE, FACTORY_TYPE> > {
1887};
1888
1889 // ========================================
1890 // private struct ManagedPtr_DefaultDeleter
1891 // ========================================
1892
1893/// This `struct` provides a function-like managed pointer deleter that
1894/// invokes `delete` with the passed pointer.
1895///
1896/// See @ref bslma_managedptr
1897template <class MANAGED_TYPE>
1899
1900 // CLASS METHODS
1901
1902 /// Cast the specified `ptr` to (template parameter) type
1903 /// `MANAGED_TYPE *`, and then call `delete` with the cast pointer.
1904 static void deleter(void *ptr, void *);
1905};
1906
1907// ============================================================================
1908// INLINE DEFINITIONS
1909// ============================================================================
1910
1911 // ----------------------------
1912 // private class ManagedPtr_Ref
1913 // ----------------------------
1914
1915// CREATORS
1916template <class TARGET_TYPE>
1917inline
1919 TARGET_TYPE *target)
1920: d_base_p(base)
1921, d_cast_p(target)
1922{
1923 BSLS_ASSERT_SAFE(0 != base);
1924}
1925
1926template <class TARGET_TYPE>
1927inline
1932
1933// ACCESSORS
1934template <class TARGET_TYPE>
1935inline
1937{
1938 return d_base_p;
1939}
1940
1941template <class TARGET_TYPE>
1942inline
1944{
1945 return d_cast_p;
1946}
1947
1948 // ----------------
1949 // class ManagedPtr
1950 // ----------------
1951
1952template <class TARGET_TYPE>
1953class ManagedPtr<volatile TARGET_TYPE>;
1954 // This specialization is declared but not defined, in order to provide an
1955 // early compile-fail check to catch misuse of managed pointer to
1956 // 'volatile' types, which is explicitly called out as not supported in the
1957 // primary class template contract.
1958
1959template <class TARGET_TYPE>
1960class ManagedPtr<TARGET_TYPE&>;
1961 // This specialization is declared but not defined, in order to provide an
1962 // early compile-fail check to catch misuse of managed pointer to reference
1963 // types, which is explicitly called out as not supported in the primary
1964 // class template contract.
1965
1966#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
1967template <class TARGET_TYPE>
1968class ManagedPtr<TARGET_TYPE&&>;
1969 // This specialization is declared but not defined, in order to provide an
1970 // early compile-fail check to catch misuse of managed pointer to reference
1971 // types, which is explicitly called out as not supported in the primary
1972 // class template contract.
1973#endif
1974
1975// PRIVATE CLASS METHODS
1976template <class TARGET_TYPE>
1977inline
1979{
1980 return PointerUtil::voidify(ptr);
1981}
1982
1983template <class TARGET_TYPE>
1984template <class MANAGED_TYPE>
1985inline
1986void *
1987ManagedPtr<TARGET_TYPE>::stripCompletePointerType(MANAGED_TYPE *ptr)
1988{
1989 return PointerUtil::voidify(ptr);
1990}
1991
1992// PRIVATE MANIPULATORS
1993template <class TARGET_TYPE>
1994template <class MANAGED_TYPE>
1995inline
1996void ManagedPtr<TARGET_TYPE>::loadImp(MANAGED_TYPE *ptr,
1997 void *cookie,
1998 DeleterFunc deleter)
1999{
2001 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2002
2003 d_members.runDeleter();
2004 d_members.set(stripCompletePointerType(ptr), cookie, deleter);
2005 d_members.setAliasPtr(stripBasePointerType(ptr));
2006}
2007
2008// CREATORS
2009template <class TARGET_TYPE>
2010inline
2012: d_members()
2013{
2014}
2015
2016template <class TARGET_TYPE>
2017inline
2022
2023template <class TARGET_TYPE>
2024template <class MANAGED_TYPE>
2025inline
2027: d_members(stripCompletePointerType(ptr),
2028 0,
2029 &ManagedPtr_DefaultDeleter<MANAGED_TYPE>::deleter,
2030 stripBasePointerType(ptr))
2031{
2033}
2034
2035template <class TARGET_TYPE>
2036inline
2039: d_members(*ref.base())
2040{
2041 d_members.setAliasPtr(stripBasePointerType(ref.target()));
2042}
2043
2044template <class TARGET_TYPE>
2045inline
2047: d_members(original.d_members)
2048{
2049}
2050
2051template <class TARGET_TYPE>
2052inline
2055: d_members(MoveUtil::access(original).d_members)
2056{
2057}
2058
2059#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
2060 template <class TARGET_TYPE>
2061 template <class BDE_OTHER_TYPE>
2062 inline
2064 ManagedPtr<BDE_OTHER_TYPE> &&original,
2065 typename bsl::enable_if<bsl::is_convertible<BDE_OTHER_TYPE *,
2066 TARGET_TYPE *>::value,
2069 : d_members(original.d_members)
2070#elif defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
2071 // sun compiler version 12.3 and earlier
2072 template <class TARGET_TYPE>
2073 template <class BDE_OTHER_TYPE>
2074 inline
2078 : d_members(MoveUtil::access(original).d_members)
2079#else // c++03 except old (version <= 12.3) sun compilers
2080 template <class TARGET_TYPE>
2081 template <class BDE_OTHER_TYPE>
2082 inline
2085 typename bsl::enable_if<bsl::is_convertible<BDE_OTHER_TYPE *,
2086 TARGET_TYPE *>::value,
2089 : d_members(MoveUtil::access(original).d_members)
2090#endif
2091{
2092 // This constructor cannot be constrained using a type trait on old Sun
2093 // compilers (version <= 12.3), so we need the check here.
2094 #if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
2095 BSLMF_ASSERT((bsl::is_convertible<BDE_OTHER_TYPE *,
2096 TARGET_TYPE *>::value));
2097 #endif
2098
2099 // To deal with the possibility of multiple inheritance, we need to
2100 // "correct" the target pointer.
2101 d_members.setAliasPtr(
2102 stripBasePointerType(
2103 static_cast<TARGET_TYPE *>(
2104 static_cast<BDE_OTHER_TYPE *>(
2105 d_members.pointer()))));
2106}
2107
2108
2109template <class TARGET_TYPE>
2110template <class ALIASED_TYPE>
2111inline
2113 TARGET_TYPE *ptr)
2114: d_members()
2115{
2116 BSLS_ASSERT_SAFE(0 != alias.get() || 0 == ptr);
2117
2118 if (0 != ptr) {
2119 d_members.move(&alias.d_members);
2120 d_members.setAliasPtr(stripBasePointerType(ptr));
2121 }
2122}
2123
2124template <class TARGET_TYPE>
2125template <class ALIASED_TYPE>
2126inline
2128#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
2130#else
2132#endif
2133 TARGET_TYPE *ptr)
2134: d_members()
2135{
2136 ManagedPtr<ALIASED_TYPE>& lvalue = alias;
2137
2138 BSLS_ASSERT_SAFE(0 != lvalue.get() || 0 == ptr);
2139
2140 if (0 != ptr) {
2141 d_members.move(&lvalue.d_members);
2142 d_members.setAliasPtr(stripBasePointerType(ptr));
2143 }
2144}
2145
2146template <class TARGET_TYPE>
2147template <class MANAGED_TYPE, class FACTORY_TYPE>
2148inline
2149ManagedPtr<TARGET_TYPE>::ManagedPtr(MANAGED_TYPE *ptr, FACTORY_TYPE *factory)
2150: d_members(stripCompletePointerType(ptr),
2151 factory,
2152 &ManagedPtr_FactoryDeleterType<MANAGED_TYPE,
2153 FACTORY_TYPE>::type::deleter,
2154 stripBasePointerType(ptr))
2155{
2157 BSLS_ASSERT_SAFE(0 != factory || 0 == ptr);
2158}
2159
2160template <class TARGET_TYPE>
2161inline
2166
2167template <class TARGET_TYPE>
2168template <class FACTORY_TYPE>
2169inline
2171: d_members()
2172{
2173}
2174
2175template <class TARGET_TYPE>
2176inline
2178 void *cookie,
2179 DeleterFunc deleter)
2180: d_members(stripBasePointerType(ptr), cookie, deleter)
2181{
2182 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2183}
2184
2185template <class TARGET_TYPE>
2186template <class MANAGED_TYPE>
2187inline
2189 void *cookie,
2190 DeleterFunc deleter)
2191: d_members(stripCompletePointerType(ptr),
2192 cookie,
2193 deleter,
2194 stripBasePointerType(ptr))
2195{
2197
2198 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2199}
2200
2201#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2202template <class TARGET_TYPE>
2203template <class MANAGED_TYPE, class MANAGED_BASE>
2204inline
2206 MANAGED_TYPE *ptr,
2207 void *cookie,
2208 void (*deleter)(MANAGED_BASE *, void *))
2209: d_members(stripCompletePointerType(ptr),
2210 cookie,
2211 reinterpret_cast<DeleterFunc>(deleter),
2212 stripBasePointerType(ptr))
2213{
2215 BSLMF_ASSERT((bsl::is_convertible<MANAGED_TYPE *,
2216 const MANAGED_BASE *>::value));
2217
2218 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2219}
2220
2221template <class TARGET_TYPE>
2222template <class MANAGED_TYPE,
2223 class MANAGED_BASE,
2224 class COOKIE_TYPE,
2225 class COOKIE_BASE>
2226inline
2228 MANAGED_TYPE *ptr,
2229 COOKIE_TYPE *cookie,
2230 void (*deleter)(MANAGED_BASE *, COOKIE_BASE *))
2231: d_members(stripCompletePointerType(ptr),
2232 static_cast<COOKIE_BASE *>(cookie),
2233 reinterpret_cast<DeleterFunc>(deleter),
2234 stripBasePointerType(ptr))
2235{
2237 BSLMF_ASSERT((bsl::is_convertible<MANAGED_TYPE *,
2238 const MANAGED_BASE *>::value));
2240
2241 // Note that the undefined behavior embodied in the @ref reinterpret_cast
2242 // above could be removed by inserting an additional forwarding function
2243 // truly of type 'DeleterFunc' which @ref reinterpret_cast s each pointer
2244 // argument as part of its forwarding behavior. We choose not to do this
2245 // on the grounds of simple efficiency, and there is currently no known
2246 // supported compiler that we use where this does not work as desired.
2247
2248 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2249}
2250#endif // BDE_OMIT_INTERNAL_DEPRECATED
2251
2252template <class TARGET_TYPE>
2253inline
2255{
2256 d_members.runDeleter();
2257}
2258
2259// MANIPULATORS
2260template <class TARGET_TYPE>
2261inline
2264{
2265 d_members.moveAssign(&rhs.d_members);
2266 return *this;
2267}
2268
2269template <class TARGET_TYPE>
2270inline
2274{
2275 ManagedPtr& lvalue = rhs;
2276 d_members.moveAssign(&lvalue.d_members);
2277 return *this;
2278}
2279
2280#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
2281 template <class TARGET_TYPE>
2282 template <class BDE_OTHER_TYPE>
2283 inline
2284 typename bsl::enable_if<
2289#elif defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
2290 // sun compiler version 12.3 and earlier
2291 template <class TARGET_TYPE>
2292 template <class BDE_OTHER_TYPE>
2293 inline
2298#else // c++03 except old (version <= 12.3) sun compilers
2299 template <class TARGET_TYPE>
2300 template <class BDE_OTHER_TYPE>
2301 inline
2302 typename bsl::enable_if<
2308#endif
2309{
2310 // This operator cannot be constrained using a type trait on Sun, so we
2311 // need the check here.
2312 #if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
2313 BSLMF_ASSERT((bsl::is_convertible<BDE_OTHER_TYPE *,
2314 TARGET_TYPE *>::value));
2315 #endif
2316
2317 ManagedPtr<BDE_OTHER_TYPE>& lvalue = rhs;
2318 d_members.moveAssign(&lvalue.d_members);
2319
2320 // To deal with the possibility of multiple inheritance, we need to
2321 // "correct" the target pointer.
2322 d_members.setAliasPtr(
2323 stripBasePointerType(
2324 static_cast<TARGET_TYPE *>(
2325 static_cast<BDE_OTHER_TYPE *>(
2326 d_members.pointer()))));
2327
2328 return *this;
2329}
2330
2331template <class TARGET_TYPE>
2332inline
2336{
2337 d_members.moveAssign(ref.base());
2338 d_members.setAliasPtr(stripBasePointerType(ref.target()));
2339 return *this;
2340}
2341
2342template <class TARGET_TYPE>
2343inline
2346{
2347 this->reset();
2348 return *this;
2349}
2350
2351template <class TARGET_TYPE>
2352template <class REFERENCED_TYPE>
2353inline
2355{
2356 BSLMF_ASSERT((bsl::is_convertible<TARGET_TYPE *,
2357 REFERENCED_TYPE *>::value));
2358
2359 return ManagedPtr_Ref<REFERENCED_TYPE>(&d_members,
2360 static_cast<REFERENCED_TYPE *>(
2361 static_cast<TARGET_TYPE *>(d_members.pointer())));
2362}
2363
2364template <class TARGET_TYPE>
2365inline
2367{
2368 reset();
2369}
2370
2371template <class TARGET_TYPE>
2372template <class MANAGED_TYPE>
2373inline
2374void ManagedPtr<TARGET_TYPE>::load(MANAGED_TYPE *ptr)
2375{
2377
2379 this->loadImp(ptr,
2380 static_cast<void *>(Default::allocator()),
2381 &DeleterFactory::deleter);
2382}
2383
2384template <class TARGET_TYPE>
2385template <class MANAGED_TYPE, class FACTORY_TYPE>
2386inline
2387void ManagedPtr<TARGET_TYPE>::load(MANAGED_TYPE *ptr, FACTORY_TYPE *factory)
2388{
2390 BSLS_ASSERT_SAFE(0 != factory || 0 == ptr);
2391
2392 typedef typename
2394 DeleterFactory;
2395
2396 this->loadImp(ptr, static_cast<void *>(factory), &DeleterFactory::deleter);
2397}
2398
2399template <class TARGET_TYPE>
2400template <class MANAGED_TYPE>
2401inline
2402void ManagedPtr<TARGET_TYPE>::load(MANAGED_TYPE *ptr,
2403 void *cookie,
2404 DeleterFunc deleter)
2405{
2407 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2408
2409 this->loadImp(ptr, cookie, deleter);
2410}
2411
2412template <class TARGET_TYPE>
2413inline
2415{
2416 this->reset();
2417}
2418
2419#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2420template <class TARGET_TYPE>
2421template <class MANAGED_TYPE, class COOKIE_TYPE>
2422inline
2423void ManagedPtr<TARGET_TYPE>::load(MANAGED_TYPE *ptr,
2424 COOKIE_TYPE *cookie,
2425 DeleterFunc deleter)
2426{
2428 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2429
2430 this->loadImp(ptr, static_cast<void *>(cookie), deleter);
2431}
2432
2433template <class TARGET_TYPE>
2434template <class MANAGED_TYPE, class MANAGED_BASE>
2435inline
2437 MANAGED_TYPE *ptr,
2438 void *cookie,
2439 void (*deleter)(MANAGED_BASE *, void *))
2440{
2444 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2445
2446 this->loadImp(ptr, cookie, reinterpret_cast<DeleterFunc>(deleter));
2447}
2448
2449template <class TARGET_TYPE>
2450template <class MANAGED_TYPE,
2451 class MANAGED_BASE,
2452 class COOKIE_TYPE,
2453 class COOKIE_BASE>
2454inline
2456 MANAGED_TYPE *ptr,
2457 COOKIE_TYPE *cookie,
2458 void (*deleter)(MANAGED_BASE *, COOKIE_BASE *))
2459{
2463 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2464
2465 this->loadImp(ptr,
2466 static_cast<void *>(static_cast<COOKIE_BASE *>(cookie)),
2467 reinterpret_cast<DeleterFunc>(deleter));
2468}
2469#endif // BDE_OMIT_INTERNAL_DEPRECATED
2470
2471template <class TARGET_TYPE>
2472template <class ALIASED_TYPE>
2474 TARGET_TYPE *ptr)
2475{
2476 BSLS_ASSERT_SAFE(!ptr == !alias.get()); // both null or both non-null
2477
2478 if (ptr && alias.d_members.pointer()) {
2479 d_members.moveAssign(&alias.d_members);
2480 d_members.setAliasPtr(stripBasePointerType(ptr));
2481 }
2482 else {
2483 d_members.runDeleter();
2484 d_members.clear();
2485 }
2486}
2487
2488template <class TARGET_TYPE>
2491{
2493
2494 TARGET_TYPE *p = get();
2495
2496 // The behavior would be undefined if 'd_members.deleter()' were called
2497 // when 'p' is null.
2498
2499 if (p) {
2500 ResultType result = { p, d_members.deleter() };
2501 d_members.clear();
2502 return result; // RETURN
2503 }
2504 ResultType result = { p, ManagedPtrDeleter() };
2505 return result;
2506}
2507
2508template <class TARGET_TYPE>
2510{
2511 BSLS_ASSERT_SAFE(deleter);
2512
2513 TARGET_TYPE *result = get();
2514
2515 // The behavior is undefined if 'd_members.deleter()' is called when
2516 // 'result' is null.
2517
2518 if (result) {
2519 *deleter = d_members.deleter();
2520 d_members.clear();
2521 }
2522 return result;
2523}
2524
2525template <class TARGET_TYPE>
2526inline
2528{
2529 d_members.runDeleter();
2530 d_members.clear();
2531}
2532
2533template <class TARGET_TYPE>
2534inline
2536{
2537 d_members.swap(other.d_members);
2538}
2539
2540// ACCESSORS
2541template <class TARGET_TYPE>
2542inline
2544{
2545 return !d_members.pointer();
2546}
2547
2548template <class TARGET_TYPE>
2549inline
2551{
2552 return d_members.pointer();
2553}
2554
2555template <class TARGET_TYPE>
2556inline
2557#if defined(BSLS_PLATFORM_CMP_IBM) // last confirmed with xlC 12.1
2558ManagedPtr<TARGET_TYPE>::operator typename ManagedPtr::BoolType() const
2559#else
2561#endif
2562{
2563 return d_members.pointer()
2566}
2567
2568template <class TARGET_TYPE>
2569inline
2572{
2573 BSLS_ASSERT_SAFE(d_members.pointer());
2574
2575 return *static_cast<TARGET_TYPE *>(d_members.pointer());
2576}
2577
2578template <class TARGET_TYPE>
2579inline
2581{
2582 return static_cast<TARGET_TYPE *>(d_members.pointer());
2583}
2584
2585template <class TARGET_TYPE>
2586inline
2588{
2589 BSLS_ASSERT_SAFE(d_members.pointer());
2590
2591 return d_members.deleter();
2592}
2593
2594template <class TARGET_TYPE>
2595inline
2597{
2598 return static_cast<TARGET_TYPE *>(d_members.pointer());
2599}
2600
2601template <class TARGET_TYPE>
2602inline
2604{
2605 return get();
2606}
2607
2608// FREE FUNCTIONS
2609template <class TARGET_TYPE>
2610inline
2612{
2613 a.swap(b);
2614}
2615
2616 // --------------------
2617 // struct ManagedPtrUtil
2618 // --------------------
2619
2620template <class ELEMENT_TYPE>
2621inline
2622void ManagedPtrUtil::allocatorDeleter(void *object, void *allocator)
2623{
2624 BSLS_ASSERT(0 != object);
2625 BSLS_ASSERT(0 != allocator);
2626
2627 AllocatorUtil::deleteObject(static_cast<Allocator *>(allocator),
2628 static_cast<ELEMENT_TYPE *>(object));
2629}
2630
2631#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=14
2632
2633template <class ELEMENT_TYPE, class ALLOCATOR, class... ARGS>
2634inline
2637ManagedPtrUtil::allocateManaged(const ALLOCATOR& allocator, ARGS&&... args)
2638{
2639 return allocateManaged<ELEMENT_TYPE>(
2640 allocator.mechanism(),
2641 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
2642}
2643
2644template <class ELEMENT_TYPE, class... ARGS>
2645inline
2647{
2649
2650 typedef typename bsl::remove_cv<ELEMENT_TYPE>::type UnqualElem;
2651
2652 // Use 'allocateObject' with a separate construction step to avoid passing
2653 // the allocator to the constructed object.
2654 UnqualElem *objPtr =
2655 bslma::AllocatorUtil::allocateObject<UnqualElem>(defaultAllocator);
2656
2658 defaultAllocator, objPtr);
2659
2660 // Do not pass an allocator to the element constructor.
2661 ::new (PointerUtil::voidify(objPtr)) ELEMENT_TYPE(
2662 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
2663 proctor.release();
2664
2665 return ManagedPtr<ELEMENT_TYPE>(objPtr,
2666 defaultAllocator,
2667 &allocatorDeleter<UnqualElem>);
2668}
2669
2670template <class ELEMENT_TYPE, class... ARGS>
2671inline
2674{
2675 typedef typename bsl::remove_cv<ELEMENT_TYPE>::type UnqualElem;
2676
2677 allocator = bslma::Default::allocator(allocator);
2678
2679 ELEMENT_TYPE *objPtr = bslma::AllocatorUtil::newObject<UnqualElem>(
2680 allocator,
2681 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
2682
2683 return ManagedPtr<ELEMENT_TYPE>(objPtr,
2684 allocator,
2685 &allocatorDeleter<UnqualElem>);
2686}
2687
2688#endif
2689
2690 // --------------------------
2691 // class ManagedPtrNilDeleter
2692 // --------------------------
2693
2694// CLASS METHODS
2695template <class TARGET_TYPE>
2696inline
2698{
2699}
2700
2701 // ----------------------------------------
2702 // private struct ManagedPtr_DefaultDeleter
2703 // ----------------------------------------
2704
2705// CLASS METHODS
2706template <class MANAGED_TYPE>
2707inline
2709{
2710 delete reinterpret_cast<MANAGED_TYPE *>(ptr);
2711}
2712
2713} // close package namespace
2714
2715// ============================================================================
2716// TYPE TRAITS
2717// ============================================================================
2718
2719namespace bslmf {
2720
2721template <class TARGET_TYPE>
2722struct HasPointerSemantics<bslma::ManagedPtr<TARGET_TYPE> > : bsl::true_type
2723{
2724};
2725
2726template <class TARGET_TYPE>
2727struct IsBitwiseMoveable<bslma::ManagedPtr<TARGET_TYPE> > : bsl::true_type
2728{
2729};
2730
2731} // close namespace bslmf
2732
2733
2734namespace bsl {
2735
2736template <class TARGET_TYPE>
2738 BloombergLP::bslma::ManagedPtr<TARGET_TYPE> > : bsl::true_type
2739{
2740};
2741
2742} // close namespace bsl
2743
2744#endif // End C++11 code
2745
2746#endif
2747
2748// ----------------------------------------------------------------------------
2749// Copyright 2016 Bloomberg Finance L.P.
2750//
2751// Licensed under the Apache License, Version 2.0 (the "License");
2752// you may not use this file except in compliance with the License.
2753// You may obtain a copy of the License at
2754//
2755// http://www.apache.org/licenses/LICENSE-2.0
2756//
2757// Unless required by applicable law or agreed to in writing, software
2758// distributed under the License is distributed on an "AS IS" BASIS,
2759// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2760// See the License for the specific language governing permissions and
2761// limitations under the License.
2762// ----------------------------- END-OF-FILE ----------------------------------
2763
2764/** @} */
2765/** @} */
2766/** @} */
Definition bslma_allocator.h:545
Definition bslma_deallocateobjectproctor.h:273
PtrType release()
Definition bslma_deallocateobjectproctor.h:442
Definition bslma_managedptrdeleter.h:114
void(* Deleter)(void *managedObject, void *cookie)
Deleter function prototype used to destroy the managed pointer.
Definition bslma_managedptrdeleter.h:120
Deleter deleter() const
Return the deleter function associated with this deleter.
Definition bslma_managedptrdeleter.h:265
Definition bslma_managedptr_members.h:87
void setAliasPtr(void *alias)
Definition bslma_managedptr_members.h:308
void runDeleter() const
Definition bslma_managedptr_members.h:331
void set(void *object, void *factory, DeleterFunc deleter)
Definition bslma_managedptr_members.h:294
void * pointer() const
Definition bslma_managedptr_members.h:325
Definition bslma_managedptr.h:1092
ManagedPtr_Ref(const ManagedPtr_Ref &original)=default
~ManagedPtr_Ref()
Definition bslma_managedptr.h:1928
ManagedPtr_Ref & operator=(const ManagedPtr_Ref &original)=default
TARGET_TYPE * target() const
Return a pointer to the referenced object.
Definition bslma_managedptr.h:1943
ManagedPtr_Ref(ManagedPtr_Members *base, TARGET_TYPE *target)
Definition bslma_managedptr.h:1918
ManagedPtr_Members * base() const
Return a pointer to the managed state of a ManagedPtr object.
Definition bslma_managedptr.h:1936
Definition bslma_managedptr.h:1173
ManagedPtr(TARGET_TYPE *ptr, void *cookie, DeleterFunc deleter)
Definition bslma_managedptr.h:2177
bool operator==(bsl::nullptr_t) const
Return true if this managed pointer is empty, and false otherwise.
Definition bslma_managedptr.h:2543
ManagedPtr(bslmf::MovableRef< ManagedPtr< BDE_OTHER_TYPE > > original, typename bsl::enable_if< bsl::is_convertible< BDE_OTHER_TYPE *, TARGET_TYPE * >::value, ManagedPtr_TraitConstraint >::type=ManagedPtr_TraitConstraint()) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2083
TARGET_TYPE * get() const
Definition bslma_managedptr.h:2596
void load(bsl::nullptr_t=0, void *cookie=0, DeleterFunc deleter=0)
Definition bslma_managedptr.h:2414
void load(MANAGED_TYPE *ptr, FACTORY_TYPE *factory)
Definition bslma_managedptr.h:2387
TARGET_TYPE * release(ManagedPtrDeleter *deleter)
Definition bslma_managedptr.h:2509
ManagedPtr(ManagedPtr< ALIASED_TYPE > &alias, TARGET_TYPE *ptr)
Definition bslma_managedptr.h:2112
ManagedPtr(bsl::nullptr_t, FACTORY_TYPE *factory)
Definition bslma_managedptr.h:2170
ManagedPtr(MANAGED_TYPE *ptr, COOKIE_TYPE *cookie, void(*deleter)(MANAGED_BASE *, COOKIE_BASE *))
Definition bslma_managedptr.h:2227
TARGET_TYPE * ptr() const
Definition bslma_managedptr.h:2603
~ManagedPtr()
Definition bslma_managedptr.h:2254
bslmf::AddReference< TARGET_TYPE >::Type operator*() const
Definition bslma_managedptr.h:2571
const ManagedPtrDeleter & deleter() const
Definition bslma_managedptr.h:2587
ManagedPtr(bsl::nullptr_t)
Definition bslma_managedptr.h:2018
ManagedPtr & operator=(ManagedPtr_Ref< TARGET_TYPE > ref) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2334
ManagedPtr(MANAGED_TYPE *ptr)
Definition bslma_managedptr.h:2026
void load(MANAGED_TYPE *ptr, COOKIE_TYPE *cookie, void(*deleter)(MANAGED_BASE *, COOKIE_BASE *))
Definition bslma_managedptr.h:2455
void swap(ManagedPtr &other)
Definition bslma_managedptr.h:2535
ManagedPtr(bsl::nullptr_t, bsl::nullptr_t)
Definition bslma_managedptr.h:2162
void load(MANAGED_TYPE *ptr)
Definition bslma_managedptr.h:2374
ManagedPtr & operator=(bslmf::MovableRef< ManagedPtr > rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2272
ManagedPtr(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter)
Definition bslma_managedptr.h:2188
ManagedPtr()
Create an empty managed pointer.
Definition bslma_managedptr.h:2011
void load(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter)
Definition bslma_managedptr.h:2402
ManagedPtr(MANAGED_TYPE *ptr, FACTORY_TYPE *factory)
Definition bslma_managedptr.h:2149
void load(MANAGED_TYPE *ptr, COOKIE_TYPE *cookie, DeleterFunc deleter)
Definition bslma_managedptr.h:2423
ManagedPtr & operator=(bsl::nullptr_t)
Definition bslma_managedptr.h:2345
void load(MANAGED_TYPE *ptr, void *cookie, void(*deleter)(MANAGED_BASE *, void *))
Definition bslma_managedptr.h:2436
ManagedPtr(MANAGED_TYPE *ptr, void *cookie, void(*deleter)(MANAGED_BASE *, void *))
Definition bslma_managedptr.h:2205
TARGET_TYPE * operator->() const
Definition bslma_managedptr.h:2580
ManagedPtr(bslmf::MovableRef< ManagedPtr > original) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2053
void clear()
Definition bslma_managedptr.h:2366
bsl::enable_if< bsl::is_convertible< BDE_OTHER_TYPE *, TARGET_TYPE * >::value, ManagedPtr< TARGET_TYPE > >::type & operator=(bslmf::MovableRef< ManagedPtr< BDE_OTHER_TYPE > > rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2305
ManagedPtr & operator=(ManagedPtr &rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2263
TARGET_TYPE element_type
Alias to the TARGET_TYPE template parameter.
Definition bslma_managedptr.h:1183
ManagedPtr(bslmf::MovableRef< ManagedPtr< ALIASED_TYPE > > alias, TARGET_TYPE *ptr)
Definition bslma_managedptr.h:2127
ManagedPtr_PairProxy< TARGET_TYPE, ManagedPtrDeleter > release()
Definition bslma_managedptr.h:2490
ManagedPtr(ManagedPtr_Ref< TARGET_TYPE > ref) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2037
friend class ManagedPtr
Definition bslma_managedptr.h:1282
bool operator!=(bsl::nullptr_t) const
Return false if this managed pointer is empty, and true otherwise.
Definition bslma_managedptr.h:2550
ManagedPtr(ManagedPtr &original) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2046
void reset()
Definition bslma_managedptr.h:2527
void loadAlias(ManagedPtr< ALIASED_TYPE > &alias, TARGET_TYPE *ptr)
Definition bslma_managedptr.h:2473
ManagedPtrDeleter::Deleter DeleterFunc
Definition bslma_managedptr.h:1180
Definition bslmf_movableref.h:752
static BoolType trueValue()
Return a value that converts to the bool value true.
Definition bsls_unspecifiedbool.h:223
int UnspecifiedBool::* BoolType
Definition bsls_unspecifiedbool.h:190
static BoolType falseValue()
Return a value that converts to the bool value false.
Definition bsls_unspecifiedbool.h:215
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
Definition bdlat_valuetypefunctions.h:939
BloombergLP::bsls::Nullptr_Impl::Type nullptr_t
Definition bsls_nullptr.h:283
Definition baljsn_encoder_testtypes.h:76
Definition bdlbb_blob.h:579
Definition bslmf_conditional.h:123
Definition bslmf_enableif.h:530
Definition bslmf_isconvertible.h:875
Definition bslmf_isnothrowmoveconstructible.h:361
Definition bslmf_isvoid.h:138
remove_const< typenameremove_volatile< t_TYPE >::type >::type type
Definition bslmf_removecv.h:128
static void deleteObject(const t_ALLOCATOR &allocator, t_POINTER p)
Definition bslma_allocatorutil.h:959
static Allocator * allocator(Allocator *basicAllocator=0)
Definition bslma_default.h:913
static Allocator * defaultAllocator()
Definition bslma_default.h:905
Definition bslma_managedptr.h:1861
static void deleter(void *, void *)
Deleter function that does nothing.
Definition bslma_managedptr.h:2697
Definition bslma_managedptr.h:1792
static ManagedPtr< ELEMENT_TYPE > makeManaged(ARGS &&... args)
Definition bslma_managedptr.h:2646
static void allocatorDeleter(void *object, void *allocator)
Definition bslma_managedptr.h:2622
static ManagedPtr< ELEMENT_TYPE > allocateManaged(bslma::Allocator *allocator, ARGS &&... args)
Definition bslma_managedptr.h:2673
static void noOpDeleter(void *, void *)
Deleter function that does nothing.
Definition bslma_managedptr.h:1898
static void deleter(void *ptr, void *)
Definition bslma_managedptr.h:2708
Definition bslma_managedptr.h:1886
Definition bslma_managedptr_factorydeleter.h:73
Definition bslma_managedptr_pairproxy.h:83
Definition bslma_managedptr.h:1144
static BSLS_KEYWORD_CONSTEXPR void * voidify(TYPE *address) BSLS_KEYWORD_NOEXCEPT
Definition bslma_pointerutil.h:350
bsl::add_lvalue_reference< t_TYPE >::type Type
Definition bslmf_addreference.h:191
Definition bslmf_haspointersemantics.h:83
Definition bslmf_isbitwisemoveable.h:718
Definition bslmf_movableref.h:795