BDE 4.14.0 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>
426/// getFirstQuoteLargerThan(double threshold, bslma::Allocator *allocator)
427/// {
428/// assert(END_QUOTE < 0 && 0 <= threshold);
429/// @endcode
430/// Next, we allocate our array with extra room to mark the beginning and end
431/// with a special `END_QUOTE` value:
432/// @code
433/// const int MAX_QUOTES = 100;
434/// int numBytes = (MAX_QUOTES + 2) * sizeof(double);
435/// double *quotes = (double *) allocator->allocate(numBytes);
436/// quotes[0] = quotes[MAX_QUOTES + 1] = END_QUOTE;
437/// @endcode
438/// Then, we create a managed pointer to the entire array:
439/// @code
440/// bslma::ManagedPtr<double> managedQuotes(quotes, allocator);
441/// @endcode
442/// Next, we read quotes until the array is full, keeping track of the first
443/// quote that exceeds the threshold.
444/// @code
445/// double *finger = 0;
446///
447/// for (int i = 1; i <= MAX_QUOTES; ++i) {
448/// double quote = Ticker::getQuote();
449/// quotes[i] = quote;
450/// if (!finger && quote > threshold) {
451/// finger = &quotes[i];
452/// }
453/// }
454/// @endcode
455/// Now, we use the alias constructor to create a managed pointer that points to
456/// the desired value (the finger) but manages the entire array:
457/// @code
458/// return bslma::ManagedPtr<double>(managedQuotes, finger);
459/// }
460/// @endcode
461/// Then, our main program calls `getFirstQuoteLargerThan` like this:
462/// @code
463/// int aliasExample()
464/// {
465/// bslma::TestAllocator ta;
466/// bslma::ManagedPtr<double> result = getFirstQuoteLargerThan(16.00, &ta);
467/// assert(*result > 16.00);
468/// assert(1 == ta.numBlocksInUse());
469/// if (g_verbose) bsl::cout << "Found quote: " << *result << bsl::endl;
470/// @endcode
471/// Next, we also print the preceding 5 quotes in last-to-first order:
472/// @code
473/// if (g_verbose) bsl::cout << "Preceded by:";
474/// int i;
475/// for (i = -1; i >= -5; --i) {
476/// double quote = result.get()[i];
477/// if (END_QUOTE == quote) {
478/// break;
479/// }
480/// assert(quote < *result);
481/// if (g_verbose) bsl::cout << ' ' << quote;
482/// }
483/// if (g_verbose) bsl::cout << bsl::endl;
484/// @endcode
485/// Then, to move the finger, e.g., to the last position printed, one must be
486/// careful to retain the ownership of the entire array. Using the statement
487/// `result.load(result.get()-i)` would be an error, because it would first
488/// compute the pointer value `result.get()-i` of the argument, then release the
489/// entire array before starting to manage what has now become an invalid
490/// pointer. Instead, `result` must retain its ownership to the entire array,
491/// which can be attained by:
492/// @code
493/// result.loadAlias(result, result.get()-i);
494/// @endcode
495/// Finally, if we reset the result pointer, the entire array is deallocated:
496/// @code
497/// result.reset();
498/// assert(0 == ta.numBlocksInUse());
499/// assert(0 == ta.numBytesInUse());
500///
501/// return 0;
502/// }
503/// @endcode
504///
505/// ### Example 3: Dynamic Objects and Factories {#bslma_managedptr-example-3-dynamic-objects-and-factories}
506///
507///
508/// Suppose we want to track the number of objects currently managed by
509/// `ManagedPtr` objects.
510///
511/// First we define a factory type that holds an allocator and a usage-counter.
512/// Note that such a type cannot sensibly be copied, as the notion `count`
513/// becomes confused.
514/// @code
515/// class CountedFactory {
516/// // DATA
517/// int d_count;
518/// bslma::Allocator *d_allocator_p;
519///
520/// // NOT IMPLEMENTED
521/// CountedFactory(const CountedFactory&);
522/// CountedFactory& operator=(const CountedFactory&);
523///
524/// public:
525/// // CREATORS
526///
527/// /// Create a `CountedFactory` object which uses the supplied
528/// /// allocator `alloc`.
529/// explicit CountedFactory(bslma::Allocator *alloc = 0);
530///
531/// /// Destroy this object.
532/// ~CountedFactory();
533/// @endcode
534/// Next, we provide the `createObject` and `deleteObject` functions that are
535/// standard for factory objects. Note that the `deleteObject` function
536/// signature has the form required by `bslma::ManagedPtr` for a factory.
537/// @code
538/// // MANIPULATORS
539///
540/// /// Return a pointer to a newly allocated object of type `TYPE`
541/// /// created using its default constructor. Memory for the object
542/// /// is supplied by the allocator supplied to this factory's
543/// /// constructor, and the count of valid object is incremented.
544/// template <class TYPE>
545/// TYPE *createObject();
546///
547/// /// Destroy the object pointed to by `target` and reclaim the
548/// /// memory. Decrement the count of currently valid objects.
549/// template <class TYPE>
550/// void deleteObject(const TYPE *target);
551/// @endcode
552/// Then, we round out the class with the ability to query the `count` of
553/// currently allocated objects.
554/// @code
555/// // ACCESSORS
556/// int count() const;
557/// // Return the number of currently valid objects allocated by this
558/// // factory.
559/// };
560/// @endcode
561/// Next, we define the operations declared by the class.
562/// @code
563/// CountedFactory::CountedFactory(bslma::Allocator *alloc)
564/// : d_count(0)
565/// , d_allocator_p(bslma::Default::allocator(alloc))
566/// {
567/// }
568///
569/// CountedFactory::~CountedFactory()
570/// {
571/// assert(0 == d_count);
572/// }
573///
574/// template <class TYPE>
575/// TYPE *CountedFactory::createObject()
576/// {
577/// TYPE *result = new(*d_allocator_p)TYPE;
578/// ++d_count;
579/// return result;
580/// }
581///
582/// template <class TYPE>
583/// void CountedFactory::deleteObject(const TYPE *object)
584/// {
585/// d_allocator_p->deleteObject(object);
586/// --d_count;
587/// }
588///
589/// inline
590/// int CountedFactory::count() const
591/// {
592/// return d_count;
593/// }
594/// @endcode
595/// Then, we can create a test function to illustrate how such a factory would
596/// be used with `ManagedPtr`.
597/// @code
598/// void testCountedFactory()
599/// {
600/// @endcode
601/// Next, we declare a test allocator, and an object of our `CountedFactory`
602/// type using that allocator.
603/// @code
604/// bslma::TestAllocator ta;
605/// CountedFactory cf(&ta);
606/// @endcode
607/// Then, we open a new local scope and declare an array of managed pointers.
608/// We need a local scope in order to observe the behavior of the destructors at
609/// end of the scope, and use an array as an easy way to count more than one
610/// object.
611/// @code
612/// {
613/// bslma::ManagedPtr<int> pData[4];
614/// @endcode
615/// Next, we load each managed pointer in the array with a new `int` using our
616/// factory `cf` and assert that the factory `count` is correct after each new
617/// `int` is created.
618/// @code
619/// int i = 0;
620/// while (i != 4) {
621/// pData[i++].load(cf.createObject<int>(), &cf);
622/// assert(cf.count() == i);
623/// }
624/// @endcode
625/// Then, we `reset` the contents of a single managed pointer in the array, and
626/// assert that the factory `count` is appropriately reduced.
627/// @code
628/// pData[1].reset();
629/// assert(3 == cf.count());
630/// @endcode
631/// Next, we `load` a managed pointer with another new `int` value, again using
632/// `cf` as the factory, and assert that the `count` of valid objects remains
633/// the same (destroy one object and add another).
634/// @code
635/// pData[2].load(cf.createObject<int>(), &cf);
636/// assert(3 == cf.count());
637/// }
638/// @endcode
639/// Finally, we allow the array of managed pointers to go out of scope and
640/// confirm that when all managed objects are destroyed, the factory `count`
641/// falls to zero, and does not overshoot.
642/// @code
643/// assert(0 == cf.count());
644/// }
645/// @endcode
646///
647/// ### Example 4: Type Casting {#bslma_managedptr-example-4-type-casting}
648///
649///
650/// `ManagedPtr` objects can be implicitly and explicitly cast to different
651/// types in the same way that native pointers can.
652///
653/// #### Implicit Conversion {#bslma_managedptr-implicit-conversion}
654///
655///
656/// As with native pointers, a pointer of the type `B` that is publicly derived
657/// from the type `A`, can be directly assigned a `ManagedPtr` of `A`.
658///
659/// First, consider the following code snippets:
660/// @code
661/// void implicitCastingExample()
662/// {
663/// @endcode
664/// If the statements:
665/// @code
666/// bslma::TestAllocator localDefaultTa;
667/// bslma::TestAllocator localTa;
668///
669/// bslma::DefaultAllocatorGuard guard(&localDefaultTa);
670///
671/// int numdels = 0;
672///
673/// {
674/// B *b_p = 0;
675/// A *a_p = b_p;
676/// @endcode
677/// are legal expressions, then the statements
678/// @code
679/// bslma::ManagedPtr<A> a_mp1;
680/// bslma::ManagedPtr<B> b_mp1;
681///
682/// assert(!a_mp1 && !b_mp1);
683///
684/// a_mp1 = b_mp1; // conversion assignment of nil ptr to nil
685/// assert(!a_mp1 && !b_mp1);
686///
687/// B *b_p2 = new (localDefaultTa) B(&numdels);
688/// bslma::ManagedPtr<B> b_mp2(b_p2); // default allocator
689/// assert(!a_mp1 && b_mp2);
690///
691/// a_mp1 = b_mp2; // conversion assignment of non-nil ptr to nil
692/// assert(a_mp1 && !b_mp2);
693///
694/// B *b_p3 = new (localTa) B(&numdels);
695/// bslma::ManagedPtr<B> b_mp3(b_p3, &localTa);
696/// assert(a_mp1 && b_mp3);
697///
698/// a_mp1 = b_mp3; // conversion assignment of non-nil to non-nil
699/// assert(a_mp1 && !b_mp3);
700///
701/// a_mp1 = b_mp3; // conversion assignment of nil to non-nil
702/// assert(!a_mp1 && !b_mp3);
703///
704/// // constructor conversion init with nil
705/// bslma::ManagedPtr<A> a_mp4(b_mp3, b_mp3.get());
706/// assert(!a_mp4 && !b_mp3);
707///
708/// // constructor conversion init with non-nil
709/// B *p_b5 = new (localTa) B(&numdels);
710/// bslma::ManagedPtr<B> b_mp5(p_b5, &localTa);
711/// bslma::ManagedPtr<A> a_mp5(b_mp5, b_mp5.get());
712/// assert(a_mp5 && !b_mp5);
713/// assert(a_mp5.get() == p_b5);
714///
715/// // constructor conversion init with non-nil
716/// B *p_b6 = new (localTa) B(&numdels);
717/// bslma::ManagedPtr<B> b_mp6(p_b6, &localTa);
718/// bslma::ManagedPtr<A> a_mp6(b_mp6);
719/// assert(a_mp6 && !b_mp6);
720/// assert(a_mp6.get() == p_b6);
721///
722/// struct S {
723/// int d_i[10];
724/// };
725///
726/// assert(200 == numdels);
727/// }
728///
729/// assert(400 == numdels);
730/// } // implicitCastingExample()
731/// @endcode
732///
733/// #### Explicit Conversion {#bslma_managedptr-explicit-conversion}
734///
735///
736/// Through "aliasing", a managed pointer of any type can be explicitly
737/// converted to a managed pointer of any other type using any legal cast
738/// expression. For example, to static-cast a managed pointer of type A to a
739/// managed pointer of type B, one can simply do the following:
740/// @code
741/// void explicitCastingExample() {
742///
743/// bslma::ManagedPtr<A> a_mp;
744/// bslma::ManagedPtr<B> b_mp1(a_mp, static_cast<B *>(a_mp.get()));
745/// @endcode
746/// or even use the less safe "C"-style casts:
747/// @code
748/// bslma::ManagedPtr<B> b_mp2(a_mp, (B *)(a_mp.get()));
749///
750/// } // explicitCastingExample()
751/// @endcode
752/// Note that when using dynamic cast, if the cast fails, the target managed
753/// pointer will be reset to an unset state, and the source will not be
754/// modified. Consider for example the following snippet of code:
755/// @code
756/// void processPolymorphicObject(bslma::ManagedPtr<A> aPtr,
757/// bool *castSucceeded)
758/// {
759/// bslma::ManagedPtr<B> bPtr(aPtr, dynamic_cast<B *>(aPtr.get()));
760/// if (bPtr) {
761/// assert(!aPtr);
762/// *castSucceeded = true;
763/// }
764/// else {
765/// assert(aPtr);
766/// *castSucceeded = false;
767/// }
768/// }
769/// @endcode
770/// If the value of `aPtr` can be dynamically cast to `B *` then ownership is
771/// transferred to `bPtr`; otherwise, `aPtr` is to be modified. As previously
772/// stated, the managed object will be destroyed correctly regardless of how it
773/// is cast.
774///
775/// ### Example 5: Inplace Object Creation {#bslma_managedptr-example-5-inplace-object-creation}
776///
777///
778/// Suppose we want to allocate memory for an object, construct it in place, and
779/// obtain a managed pointer referring to this object. This can be done in one
780/// step using two free functions provided in `bslma::ManagedPtrUtil`.
781///
782/// First, we create a simple class clearly showing the features of these
783/// functions. Note that this class does not define the
784/// `bslma::UsesBslmaAllocator` trait. It is done intentionally for
785/// illustration purposes only, and definitely is *not* *recommended* in
786/// production code. The class has an elided interface (i.e., copy constructor
787/// and copy-assignment operator are not included for brevity):
788/// @code
789/// /// Simple class that stores a copy of a null-terminated C-style string.
790/// class String {
791///
792/// private:
793/// // DATA
794/// char *d_str_p; // stored value (owned)
795/// bslma::Allocator *d_alloc_p; // allocator to allocate any dynamic
796/// // memory (held, not owned)
797///
798/// public:
799/// // CREATORS
800///
801/// /// Create an object having the same value as the specified `str`
802/// /// using the specified `alloc` to supply memory.
803/// String(const char *str, bslma::Allocator *alloc)
804/// : d_alloc_p(alloc)
805/// {
806/// assert(str);
807/// assert(alloc);
808///
809/// std::size_t length = std::strlen(str);
810///
811/// d_str_p = static_cast<char *>(d_alloc_p->allocate(length + 1));
812/// std::strncpy(d_str_p, str, length + 1);
813/// }
814///
815/// /// Destroy this object.
816/// ~String()
817/// {
818/// d_alloc_p->deallocate(d_str_p);
819/// }
820///
821/// // ACCESSORS
822///
823/// /// Return a pointer providing modifiable access to the allocator
824/// /// associated with this `String`.
825/// bslma::Allocator *allocator() const
826/// {
827/// return d_alloc_p;
828/// }
829/// };
830/// @endcode
831/// Next, we create a code fragment that will construct a managed `String`
832/// object using the default allocator to supply memory:
833/// @code
834/// void testInplaceCreation()
835/// {
836/// @endcode
837/// Suppose we want to have a different allocator supply memory allocated by the
838/// object:
839/// @code
840/// bslma::TestAllocator ta;
841/// bsls::Types::Int64 testBytesInUse = ta.numBytesInUse();
842///
843/// assert(0 == testBytesInUse);
844///
845/// bslma::TestAllocator da;
846/// bslma::DefaultAllocatorGuard dag(&da);
847/// bsls::Types::Int64 defaultBytesInUse = da.numBytesInUse();
848///
849/// assert(0 == defaultBytesInUse);
850/// @endcode
851/// Then, create a string to copy:
852/// @code
853/// const char *STR = "Test string";
854/// const int STR_LENGTH = static_cast<int>(std::strlen(STR));
855/// @endcode
856/// Next, dynamically create an object and obtain the managed pointer referring
857/// to it using the `bslma::ManagedPtrUtil::makeManaged` function:
858/// @code
859/// {
860/// bslma::ManagedPtr<String> stringManagedPtr =
861/// bslma::ManagedPtrUtil::makeManaged<String>(STR, &ta);
862/// @endcode
863/// Note that memory for the object itself is supplied by the default allocator,
864/// while memory for the copy of the passed string is supplied by another
865/// allocator:
866/// @code
867/// assert(static_cast<int>(sizeof(String)) <= da.numBytesInUse());
868/// assert(&ta == stringManagedPtr->allocator());
869/// assert(STR_LENGTH + 1 == ta.numBytesInUse());
870/// }
871/// @endcode
872/// Then, make sure that all allocated memory is successfully released after
873/// managed pointer destruction:
874/// @code
875/// assert(0 == da.numBytesInUse());
876/// assert(0 == ta.numBytesInUse());
877/// @endcode
878/// If you want to use an allocator other than the default allocator, then the
879/// `allocateManaged` function should be used instead:
880/// @code
881/// bslma::TestAllocator oa;
882/// bsls::Types::Int64 objectBytesInUse = oa.numBytesInUse();
883/// assert(0 == objectBytesInUse);
884///
885/// {
886/// bslma::ManagedPtr<String> stringManagedPtr =
887/// bslma::ManagedPtrUtil::allocateManaged<String>(&oa, STR, &ta);
888///
889/// assert(static_cast<int>(sizeof(String)) <= oa.numBytesInUse());
890/// assert(&ta == stringManagedPtr->allocator());
891/// assert(STR_LENGTH + 1 == ta.numBytesInUse());
892/// assert(0 == da.numBytesInUse());
893/// }
894///
895/// assert(0 == da.numBytesInUse());
896/// assert(0 == ta.numBytesInUse());
897/// assert(0 == oa.numBytesInUse());
898/// }
899/// @endcode
900/// Next, let's look at a more common scenario where the object's type uses
901/// `bslma` allocators. In that case `allocateManaged` implicitly passes the
902/// supplied allocator to the object's constructor as an extra argument in the
903/// final position.
904///
905/// The second example class almost completely repeats the first one, except
906/// that it explicitly defines the `bslma::UsesBslmaAllocator` trait:
907/// @code
908/// // Simple class that stores a copy of a null-terminated C-style string
909/// // and explicitly claims to use `bslma` allocators.
910/// class StringAlloc {
911///
912/// private:
913/// // DATA
914/// char *d_str_p; // stored value (owned)
915/// bslma::Allocator *d_alloc_p; // allocator to allocate any dynamic
916/// // memory (held, not owned)
917///
918/// public:
919/// // TRAITS
920/// BSLMF_NESTED_TRAIT_DECLARATION(StringAlloc, bslma::UsesBslmaAllocator);
921///
922/// // CREATORS
923///
924/// /// Create an object having the same value as the specified `str`.
925/// /// Optionally specify a `basicAllocator` used to supply memory. If
926/// /// `basicAllocator` is 0, the currently installed default allocator
927/// /// is used.
928/// StringAlloc(const char *str, bslma::Allocator *basicAllocator = 0)
929/// : d_alloc_p(bslma::Default::allocator(basicAllocator))
930/// {
931/// assert(str);
932///
933/// std::size_t length = std::strlen(str);
934///
935/// d_str_p = static_cast<char *>(d_alloc_p->allocate(length + 1));
936/// std::strncpy(d_str_p, str, length + 1);
937/// }
938///
939/// /// Destroy this object.
940/// ~StringAlloc()
941/// {
942/// d_alloc_p->deallocate(d_str_p);
943/// }
944///
945/// // ACCESSORS
946///
947/// /// Return a pointer providing modifiable access to the allocator
948/// /// associated with this `StringAlloc`.
949/// bslma::Allocator *allocator() const
950/// {
951/// return d_alloc_p;
952/// }
953/// };
954/// @endcode
955/// Then, let's create two managed objects using both `makeManaged` and
956/// `allocateManaged`:
957/// @code
958/// void testUsesAllocatorInplaceCreation()
959/// {
960/// bslma::TestAllocator ta;
961/// bsls::Types::Int64 testBytesInUse = ta.numBytesInUse();
962///
963/// assert(0 == testBytesInUse);
964///
965/// bslma::TestAllocator da;
966/// bslma::DefaultAllocatorGuard dag(&da);
967/// bsls::Types::Int64 defaultBytesInUse = da.numBytesInUse();
968///
969/// assert(0 == defaultBytesInUse);
970///
971/// const char *STR = "Test string";
972/// const int STR_LENGTH = static_cast<int>(std::strlen(STR));
973///
974/// @endcode
975/// Note that we need to explicitly supply the allocator's address to
976/// `makeManaged` to be passed to the object's constructor:
977/// @code
978/// {
979/// bslma::ManagedPtr<StringAlloc> stringManagedPtr =
980/// bslma::ManagedPtrUtil::makeManaged<StringAlloc>(STR, &ta);
981///
982/// assert(static_cast<int>(sizeof(String)) <= da.numBytesInUse());
983/// assert(&ta == stringManagedPtr->allocator());
984/// assert(STR_LENGTH + 1 == ta.numBytesInUse());
985/// }
986///
987/// @endcode
988/// But the supplied allocator is implicitly passed to the constructor by
989/// `allocateManaged`:
990/// @code
991/// {
992/// bslma::ManagedPtr<StringAlloc> stringManagedPtr =
993/// bslma::ManagedPtrUtil::allocateManaged<StringAlloc>(&ta, STR);
994///
995/// assert(static_cast<int>(sizeof(String)) + STR_LENGTH + 1 <=
996/// ta.numBytesInUse());
997/// assert(&ta == stringManagedPtr->allocator());
998/// assert(0 == da.numBytesInUse());
999/// }
1000/// @endcode
1001/// Finally, make sure that all allocated memory is successfully released after
1002/// the managed pointers (and the objects they manage) are destroyed:
1003/// @code
1004/// assert(0 == da.numBytesInUse());
1005/// assert(0 == ta.numBytesInUse());
1006/// }
1007/// @endcode
1008/// @}
1009/** @} */
1010/** @} */
1011
1012/** @addtogroup bsl
1013 * @{
1014 */
1015/** @addtogroup bslma
1016 * @{
1017 */
1018/** @addtogroup bslma_managedptr
1019 * @{
1020 */
1021
1022#include <bslscm_version.h>
1023
1024#include <bslma_allocator.h>
1025#include <bslma_constructionutil.h>
1027#include <bslma_default.h>
1032
1033#include <bslmf_addreference.h>
1034#include <bslmf_assert.h>
1035#include <bslmf_conditional.h>
1036#include <bslmf_enableif.h>
1039#include <bslmf_isclass.h>
1040#include <bslmf_isconvertible.h>
1042#include <bslmf_isvoid.h>
1043#include <bslmf_movableref.h>
1044#include <bslmf_removecv.h>
1045#include <bslmf_util.h> // 'forward(V)'
1046
1047#include <bsls_assert.h>
1048#include <bsls_compilerfeatures.h>
1049#include <bsls_keyword.h>
1050#include <bsls_nullptr.h>
1051#include <bsls_platform.h>
1052#include <bsls_unspecifiedbool.h>
1053#include <bsls_util.h> // 'forward<T>(V)'
1054
1055#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1056// Include version that can be compiled with C++03
1057// Generated on Thu Oct 21 10:11:37 2021
1058// Command line: sim_cpp11_features.pl bslma_managedptr.h
1059# define COMPILING_BSLMA_MANAGEDPTR_H
1060# include <bslma_managedptr_cpp03.h>
1061# undef COMPILING_BSLMA_MANAGEDPTR_H
1062#else
1063
1064
1065namespace bslma {
1066
1067 // =================================
1068 // private struct ManagedPtr_ImpUtil
1069 // =================================
1070
1071/// This `struct` provides a namespace for utility functions used to obtain
1072/// the necessary types of pointers.
1074
1075 // CLASS METHODS
1076
1077 /// Return the specified `address` cast as a pointer to `void`, even if
1078 /// (the template parameter) `TYPE` is cv-qualified.
1079 template <class TYPE>
1080 static void *voidify(TYPE *address) BSLS_KEYWORD_NOEXCEPT;
1081
1082 /// Return the specified `address` of a potentially cv-qualified object
1083 /// of the given (template parameter) `TYPE`, cast as a pointer to
1084 /// non-cv-qualified `TYPE`.
1085 template <class TYPE>
1086 static TYPE *unqualify(const volatile TYPE *address) BSLS_KEYWORD_NOEXCEPT;
1087};
1088 // ============================
1089 // private class ManagedPtr_Ref
1090 // ============================
1091
1092/// This class holds a managed pointer reference, returned by the implicit
1093/// conversion operator in the class `ManagedPtr`. This class is used to
1094/// allow the construction of managed pointers from temporary managed
1095/// pointer objects, since temporaries cannot bind to the reference to a
1096/// modifiable object used in the copy constructor and copy-assignment
1097/// operator for `ManagedPtr`. Note that while no members or methods of
1098/// this class template depend on the specified `TARGET_TYPE`, it is
1099/// important to carry this type into conversions to support passing
1100/// ownership of `ManagedPtr_Members` pointers when assigning or
1101/// constructing `ManagedPtr` objects.
1102///
1103/// See @ref bslma_managedptr
1104template <class TARGET_TYPE>
1106
1107 // DATA
1108 ManagedPtr_Members *d_base_p; // non-null pointer to the managed state of
1109 // a 'ManagedPtr' object
1110
1111 TARGET_TYPE *d_cast_p; // safely-cast pointer to the referenced
1112 // object
1113
1114 public:
1115 // CREATORS
1116
1117 /// Create a `ManagedPtr_Ref` object having the specified `base` value
1118 /// for its `base` attribute, and the specified `target` for its
1119 /// `target` attribute. Note that `target` (but not `base`) may be
1120 /// null.
1122
1123 ManagedPtr_Ref(const ManagedPtr_Ref& original) = default;
1124 // Create a 'ManagedPtr_Ref' object having the same 'd_base_p' value as
1125 // the specified 'original'. Note that this trivial constructor's
1126 // definition is compiler generated.
1127
1128 /// Destroy this object. Note that the referenced managed object is
1129 /// *not* destroyed.
1131
1132 // MANIPULATORS
1133 ManagedPtr_Ref& operator=(const ManagedPtr_Ref& original) = default;
1134 // Create a 'ManagedPtr_Ref' object having the same 'd_base_p' as the
1135 // specified 'original'. Note that this trivial copy-assignment
1136 // operator's definition is compiler generated.
1137
1138 // ACCESSORS
1139
1140 /// Return a pointer to the managed state of a `ManagedPtr` object.
1141 ManagedPtr_Members *base() const;
1142
1143 /// Return a pointer to the referenced object.
1144 TARGET_TYPE *target() const;
1145};
1146
1147 // =========================================
1148 // private struct ManagedPtr_TraitConstraint
1149 // =========================================
1150
1151/// This `struct` is an empty type that exists solely to enable constructor
1152/// access to be constrained by type trait.
1155 // ================
1156 // class ManagedPtr
1157 // ================
1158
1159/// This class is a "smart pointer" that refers to a *target* object
1160/// accessed via a pointer to the specified parameter type, `TARGET_TYPE`,
1161/// and that supports sole ownership of a *managed* object that is
1162/// potentially of a different type, and may be an entirely different object
1163/// from the target object. A managed pointer ensures that the object it
1164/// manages is destroyed when the managed pointer is destroyed (or
1165/// re-assigned), using the "deleter" supplied along with the managed
1166/// object. The target object referenced by a managed pointer may be
1167/// accessed using either the `->` operator, or the dereference operator
1168/// (`operator *`). The specified `TARGET_TYPE` may be `const`-qualified,
1169/// but may not be `volatile`-qualified, nor may it be a reference type.
1170///
1171/// A managed pointer may be *empty*, in which case it neither refers to a
1172/// target object nor owns a managed object. An empty managed pointer is
1173/// the equivalent of a null pointer: Such a managed pointer is not
1174/// de-referenceable, and tests as `false` in boolean expressions.
1175///
1176/// A managed pointer for which the managed object is not the same object as
1177/// the target is said to *alias* the managed object (see the section
1178/// "Aliasing" in the component-level documentation).
1179///
1180/// See @ref bslma_managedptr
1181template <class TARGET_TYPE>
1183
1184 public:
1185 // INTERFACE TYPES
1186
1187 /// Alias for a function-pointer type for functions used to destroy the
1188 /// object managed by a `ManagedPtr` object.
1190
1191 /// Alias to the `TARGET_TYPE` template parameter.
1192 typedef TARGET_TYPE element_type;
1193
1194 private:
1195 // PRIVATE TYPES
1196
1197 /// `BoolType` is an alias for an unspecified type that is implicitly
1198 /// convertible to `bool`, but will not promote to `int`. This (opaque)
1199 /// type can be used as an "unspecified boolean type" for converting a
1200 /// managed pointer to `bool` in contexts such as `if (mp) { ... }`
1201 /// without actually having a conversion to `bool` or being less-than
1202 /// comparable (either of which would also enable undesirable implicit
1203 /// comparisons of managed pointers to `int` and less-than comparisons).
1204 typedef typename bsls::UnspecifiedBool<ManagedPtr>::BoolType BoolType;
1205
1206 /// This `typedef` is a convenient alias for the utility associated with
1207 /// movable references.
1209
1210 // DATA
1211 ManagedPtr_Members d_members; // state managed by this object
1212
1213 // PRIVATE CLASS METHODS
1214
1215 /// Return the value of the specified `ptr` as a `void *`, after
1216 /// stripping all `const` and `volatile` qualifiers from `TARGET_TYPE`.
1217 /// This function avoids accidental type-safety errors when performing
1218 /// the necessary sequence of casts. Note that calling this function
1219 /// implies a conversion of the calling pointer to `TARGET_TYPE *`,
1220 /// which, in rare cases, may involve some adjustment of the pointer
1221 /// value, e.g., in the case of multiple inheritance where `TARGET_TYPE`
1222 /// is not a left-most base of the complete object type.
1223 static void *stripBasePointerType(TARGET_TYPE *ptr);
1224
1225 /// Return the value of the specified `ptr` as a `void *`, after
1226 /// stripping all `const` and `volatile` qualifiers from `MANAGED_TYPE`.
1227 /// This function avoids accidental type-safety errors when performing
1228 /// the necessary sequence of casts.
1229 template <class MANAGED_TYPE>
1230 static void *stripCompletePointerType(MANAGED_TYPE *ptr);
1231
1232 // PRIVATE MANIPULATORS
1233
1234 /// Destroy the currently managed object, if any. Then, set the target
1235 /// object of this managed pointer to be that referenced by the
1236 /// specified `ptr`, take ownership of `*ptr` as the currently managed
1237 /// object, and set a deleter that will invoke the specified `deleter`
1238 /// with the address of the currently managed object, and with the
1239 /// specified `cookie` (that the deleter can use for its own purposes),
1240 /// unless `0 == ptr`, in which case reset this managed pointer to
1241 /// empty. The behavior is undefined if `ptr` is already managed by
1242 /// another object, or if `0 == deleter && 0 != ptr`.
1243 template <class MANAGED_TYPE>
1244 void loadImp(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1245
1246 private:
1247 // NOT IMPLEMENTED
1248
1249 /// It is never defined behavior to pass a null pointer literal as a
1250 /// factory, unless the specified `ptr` is also a null pointer literal.
1251 template <class MANAGED_TYPE>
1252 ManagedPtr(MANAGED_TYPE *, bsl::nullptr_t);
1253
1254 private:
1255 // NOT IMPLEMENTED
1256
1257 /// It is never defined behavior to pass a null literal as a deleter,
1258 /// unless the `object` pointer is also a null pointer literal.
1259 template <class MANAGED_TYPE, class COOKIE_TYPE>
1260 ManagedPtr(MANAGED_TYPE *, COOKIE_TYPE *, bsl::nullptr_t);
1261
1262 private:
1263 // NOT IMPLEMENTED
1264
1265 /// It is never defined behavior to pass a null literal as a deleter,
1266 /// unless the `object` pointer is also a null pointer literal.
1267 template <class MANAGED_TYPE>
1268 void load(MANAGED_TYPE *, bsl::nullptr_t, bsl::nullptr_t);
1269 template <class COOKIE_TYPE>
1270 void load(TARGET_TYPE *, COOKIE_TYPE *, bsl::nullptr_t);
1271
1272 private:
1273 // NOT IMPLEMENTED
1274
1275 /// These two operator overloads are declared as `private` but never
1276 /// defined in order to eliminate accidental equality comparisons that
1277 /// would occur through the implicit conversion to `BoolType`. Note
1278 /// that the return type of `void` is chosen as it will often produce a
1279 /// clearer error message than relying on the `private` control failure.
1280 /// Also note that these private operators will not be needed with
1281 /// C++11, where an `explicit operator bool()` conversion operator would
1282 /// be preferred.
1283 void operator==(const ManagedPtr&) const;
1284 void operator!=(const ManagedPtr&) const;
1285
1286 // FRIENDS
1287 template <class ALIASED_TYPE>
1288 friend class ManagedPtr; // required only for alias support
1289
1290 public:
1291 // CREATORS
1292
1293 /// Create an empty managed pointer.
1295
1296 /// Create a managed pointer having a target object referenced by the
1297 /// specified `ptr`, owning the managed object `*ptr`, and having a
1298 /// deleter that will call `delete ptr` to destroy the managed object
1299 /// when invoked (e.g., when this managed pointer object is destroyed),
1300 /// unless `0 == ptr`, in which case create an empty managed pointer.
1301 /// The deleter will invoke the destructor of `MANAGED_TYPE` rather than
1302 /// the destructor of `TARGET_TYPE`. This constructor will not compile
1303 /// unless `MANAGED_TYPE *` is convertible to `TARGET_TYPE *`. Note
1304 /// that this behavior allows `ManagedPtr` to be defined for `void`
1305 /// pointers, and to call the correct destructor for the managed object,
1306 /// even if the destructor for `TARGET_TYPE` is not declared as
1307 /// `virtual`. The behavior is undefined unless the managed object (if
1308 /// any) can be destroyed by `delete`, or if the lifetime of the managed
1309 /// object is already managed by another object.
1310 template <class MANAGED_TYPE>
1311 explicit ManagedPtr(MANAGED_TYPE *ptr);
1312
1313 /// Create a managed pointer having the same target object as the
1314 /// managed pointer referenced by the specified `ref`, transfer
1315 /// ownership of the managed object owned by the managed pointer
1316 /// referenced by `ref`, and reset the managed pointer referenced by
1317 /// `ref` to empty. This constructor is used to create a managed
1318 /// pointer from a managed pointer rvalue, or from a managed pointer to
1319 /// a "compatible" type, where "compatible" means a built-in conversion
1320 /// from `COMPATIBLE_TYPE *` to `TARGET_TYPE *` is defined, e.g.,
1321 /// `derived *` to `base *`, `T *` to `const T *`, or `T *` to `void *`.
1323 BSLS_KEYWORD_NOEXCEPT; // IMPLICIT
1324
1326
1327 /// Create a managed pointer having the same target object as the
1328 /// specified `original`, transfer ownership of the object managed by
1329 /// `original` (if any) to this managed pointer, and reset `original` to
1330 /// empty.
1332
1333 /// Create a managed pointer having the same target object as the specified
1334 /// `original`, transfer ownership of the object managed by `original` (if
1335 /// any) to this managed pointer, and reset `original` to empty.
1336 /// `TARGET_TYPE` must be an accessible and unambiguous base of
1337 /// `BDE_OTHER_TYPE`
1338#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1339 template <class BDE_OTHER_TYPE>
1341 typename bsl::enable_if<
1346#elif defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
1347 // sun compiler version 12.3 and earlier
1348 template <class BDE_OTHER_TYPE>
1351#else // c++03 except old (version <= 12.3) sun compilers
1352 template <class BDE_OTHER_TYPE>
1354 typename bsl::enable_if<
1359#endif
1360
1361 /// Create a managed pointer that takes ownership of the object managed
1362 /// by the specified `alias`, but which uses the specified `ptr` to
1363 /// refer to its target object, unless `0 == ptr`, in which case create
1364 /// an empty managed pointer. Reset `alias` to empty if ownership of
1365 /// its managed object is transferred. The behavior is undefined if
1366 /// `alias` is empty, but `0 != ptr`. Note that destroying or
1367 /// re-assigning a managed pointer created with this constructor will
1368 /// destroy the object originally managed by `alias` (unless `release`
1369 /// is called first); the destructor for `*ptr` is not called directly.
1370 template <class ALIASED_TYPE>
1372 template <class ALIASED_TYPE>
1373#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1375#else
1377#endif
1378 TARGET_TYPE *ptr);
1379
1380 /// Create a managed pointer having a target object referenced by the
1381 /// specified `ptr`, owning the managed object `*ptr`, and having a
1382 /// deleter that will call `factory->deleteObject(ptr)` to destroy the
1383 /// managed object when invoked (e.g., when this managed pointer object
1384 /// is destroyed), unless `0 == ptr`, in which case create an empty
1385 /// managed pointer. The deleter will invoke the destructor of
1386 /// `MANAGED_TYPE` rather than the destructor of `TARGET_TYPE`. This
1387 /// constructor will not compile unless `MANAGED_TYPE *` is convertible
1388 /// to `TARGET_TYPE *`. 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
1391 /// is already managed by another object. Note that `bslma::Allocator`,
1392 /// and any class publicly and unambiguously derived from
1393 /// `bslma::Allocator`, meets the requirements for `FACTORY_TYPE`.
1394 template <class MANAGED_TYPE, class FACTORY_TYPE>
1395 ManagedPtr(MANAGED_TYPE *ptr, FACTORY_TYPE *factory);
1396
1397 /// Create an empty managed pointer. Note that this constructor is
1398 /// necessary to match null-pointer literal arguments, in order to break
1399 /// ambiguities and provide valid type deduction with the other
1400 /// constructor templates in this class.
1402
1403 /// Create an empty managed pointer. Note that the specified `factory`
1404 /// is ignored, as an empty managed pointer does not call its deleter.
1405 template <class FACTORY_TYPE>
1406 ManagedPtr(bsl::nullptr_t, FACTORY_TYPE *factory);
1407
1408 /// Create a managed pointer having a target object referenced by the
1409 /// specified `ptr`, owning the managed object `*ptr`, and having a
1410 /// deleter that will invoke the specified `deleter` with the address of
1411 /// the currently managed object, and with the specified `cookie` (that
1412 /// the deleter can use for its own purposes), unless `0 == ptr`, in
1413 /// which case create an empty managed pointer. The behavior is
1414 /// undefined if `ptr` is already managed by another object, or if
1415 /// `0 == deleter && 0 != ptr`. Note that this constructor is required
1416 /// only because the deprecated overloads cause an ambiguity in its
1417 /// absence; it should be removed when the deprecated overloads are
1418 /// removed.
1419 ManagedPtr(TARGET_TYPE *ptr, void *cookie, DeleterFunc deleter);
1420
1421 /// Create a managed pointer having a target object referenced by the
1422 /// specified `ptr`, owning the managed object `*ptr`, and having a
1423 /// deleter that will invoke the specified `deleter` with the address of
1424 /// the currently managed object, and with the specified `cookie` (that
1425 /// the deleter can use for its own purposes), unless `0 == ptr`, in
1426 /// which case create an empty managed pointer. This constructor will
1427 /// not compile unless `MANAGED_TYPE *` is convertible to
1428 /// `TARGET_TYPE *`. The deleter will invoke the destructor of
1429 /// `MANAGED_TYPE` rather than the destructor of `TARGET_TYPE`. The
1430 /// behavior is undefined if `ptr` is already managed by another object,
1431 /// or if `0 == deleter && 0 != ptr`.
1432 template <class MANAGED_TYPE>
1433 ManagedPtr(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1434
1435#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1436 /// [**DEPRECATED**]: Instead, use:
1437 /// @code
1438 /// template <class MANAGED_TYPE>
1439 /// ManagedPtr(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1440 /// @endcode
1441 /// Create a managed pointer having a target object referenced by the
1442 /// specified `ptr`, owning the managed object `*ptr`, and having a
1443 /// deleter that will invoke the specified `deleter` with the address of
1444 /// the currently managed object, and with the specified `cookie` (that
1445 /// the deleter can use for its own purposes), unless `0 == ptr`, in
1446 /// which case create an empty managed pointer. This constructor will
1447 /// not compile unless `MANAGED_TYPE *` is convertible to
1448 /// `TARGET_TYPE *`, and `MANAGED_TYPE *` is convertible to
1449 /// `MANAGED_BASE *`. The deleter will invoke the destructor of
1450 /// `MANAGED_TYPE` rather than the destructor of `TARGET_TYPE`. The
1451 /// behavior is undefined if `ptr` is already managed by another object,
1452 /// or if `0 == deleter && 0 != ptr`. Note that this constructor is
1453 /// needed only to avoid ambiguous type deductions when passing a null
1454 /// pointer literal as the `cookie` when the user passes a deleter
1455 /// taking a type other than `void *` for its object type. Also note
1456 /// that this function is *deprecated* as it relies on undefined
1457 /// compiler behavior for its implementation (that luckily performs as
1458 /// required on every platform supported by BDE).
1459 template <class MANAGED_TYPE, class MANAGED_BASE>
1460 ManagedPtr(MANAGED_TYPE *ptr,
1461 void *cookie,
1462 void (*deleter)(MANAGED_BASE *, void *));
1463
1464 /// [**DEPRECATED**]: Instead, use:
1465 /// @code
1466 /// template <class MANAGED_TYPE>
1467 /// ManagedPtr(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1468 /// @endcode
1469 /// Create a managed pointer having a target object referenced by the
1470 /// specified `ptr`, owning the managed object `*ptr`, and having a
1471 /// deleter that will invoke the specified `deleter` with the address of
1472 /// the currently managed object, and with the specified `cookie` (that
1473 /// the deleter can use for its own purposes), unless `0 == ptr`, in
1474 /// which case create an empty managed pointer. This constructor will
1475 /// not compile unless `MANAGED_TYPE *` is convertible to
1476 /// `TARGET_TYPE *`, and `MANAGED_TYPE *` is convertible to
1477 /// `MANAGED_BASE *`. The deleter will invoke the destructor of
1478 /// `MANAGED_TYPE` rather than the destructor of `TARGET_TYPE`. The
1479 /// behavior is undefined if `ptr` is already managed by another object,
1480 /// or if `0 == deleter && 0 != ptr`. Note that this function is
1481 /// *deprecated* as it relies on undefined compiler behavior for its
1482 /// implementation (that luckily performs as required on every platform
1483 /// supported by BDE).
1484 template <class MANAGED_TYPE,
1485 class MANAGED_BASE,
1486 class COOKIE_TYPE,
1487 class COOKIE_BASE>
1488 ManagedPtr(MANAGED_TYPE *ptr,
1489 COOKIE_TYPE *cookie,
1490 void (*deleter)(MANAGED_BASE *, COOKIE_BASE *));
1491#endif // BDE_OMIT_INTERNAL_DEPRECATED
1492
1493 /// Destroy this managed pointer object. Destroy the object managed by
1494 /// this managed pointer by invoking the user-supplied deleter, unless
1495 /// this managed pointer is empty, in which case the deleter will *not*
1496 /// be called.
1498
1499 // MANIPULATORS
1501
1502 /// If this object and the specified `rhs` manage the same object,
1503 /// return a reference to this managed pointer; otherwise, destroy the
1504 /// managed object owned by this managed pointer, transfer ownership of
1505 /// the managed object owned by `rhs` to this managed pointer, set this
1506 /// managed pointer to point to the target object referenced by `rhs`,
1507 /// reset `rhs` to empty, and return a reference to this managed
1508 /// pointer.
1511
1512 /// If this object and the specified `rhs` manage the same object,
1513 /// return a reference to this managed pointer; otherwise, destroy the
1514 /// managed object owned by this managed pointer, transfer ownership of
1515 /// the managed object owned by `rhs` to this managed pointer, set this
1516 /// managed pointer to point to the target object referenced by `rhs`,
1517 /// reset `rhs` to empty, and return a reference to this managed
1518 /// pointer. `TARGET_TYPE` must be an accessible and unambiguous base
1519 /// of `BDE_OTHER_TYPE`
1520#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
1521 template <class BDE_OTHER_TYPE>
1522 typename bsl::enable_if<
1526#elif defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
1527 // sun compiler version 12.3 and earlier
1528 template <class BDE_OTHER_TYPE>
1532#else // c++03 except old (version <= 12.3) sun compilers
1533 template <class BDE_OTHER_TYPE>
1534 typename bsl::enable_if<
1539#endif
1540
1541 /// If this object and the managed pointer reference by the specified
1542 /// `ref` manage the same object, return a reference to this managed
1543 /// pointer; otherwise, destroy the managed object owned by this managed
1544 /// pointer, transfer ownership of the managed object owned by the
1545 /// managed pointer referenced by `ref`, and set this managed pointer to
1546 /// point to the target object currently referenced the managed pointer
1547 /// referenced by `ref`; then reset the managed pointer referenced by
1548 /// `ref` to empty, and return a reference to this managed pointer.
1549 /// This operator is (implicitly) used to assign from a managed pointer
1550 /// rvalue, or from a managed pointer to a "compatible" type, where
1551 /// "compatible" means a built-in conversion from `MANAGED_TYPE *` to
1552 /// `TARGET_TYPE *` is defined, e.g., `derived *` to `base *`, `T *` to
1553 /// `const T *`, or `T *` to `void *`.
1556
1557 /// Destroy the current managed object (if any) and reset this managed
1558 /// pointer to empty.
1560
1561 /// Return a managed pointer reference, referring to this object. Note
1562 /// that this conversion operator is used implicitly to allow the
1563 /// construction of managed pointers from rvalues because temporaries
1564 /// cannot be passed by references offering modifiable access.
1565 template <class REFERENCED_TYPE>
1567
1568 /// [**DEPRECATED**] Use `reset` instead.
1569 ///
1570 /// Destroy the current managed object (if any) and reset this managed
1571 /// pointer to empty.
1572 void clear();
1573
1574 /// Destroy the currently managed object, if any. Then, set the target
1575 /// object of this managed pointer to be that referenced by the
1576 /// specified `ptr`, take ownership of `*ptr` as the currently managed
1577 /// object, and set a deleter that uses the currently installed default
1578 /// allocator to destroy the managed object when invoked (e.g., when
1579 /// this managed pointer object is destroyed), unless `0 == ptr`, in
1580 /// which case reset this managed pointer to empty. The deleter will
1581 /// invoke the destructor of `MANAGED_TYPE` rather than the destructor
1582 /// of `TARGET_TYPE`. This function will not compile unless
1583 /// `MANAGED_TYPE *` is convertible to `TARGET_TYPE *`. The behavior is
1584 /// undefined unless the managed object (if any) can be destroyed by the
1585 /// currently installed default allocator, or if the lifetime of the
1586 /// managed object is already managed by another object.
1587 template <class MANAGED_TYPE>
1588 void load(MANAGED_TYPE *ptr);
1589
1590 /// Destroy the currently managed object, if any. Then, set the target
1591 /// object of this managed pointer to be that referenced by the
1592 /// specified `ptr`, take ownership of `*ptr` as the currently managed
1593 /// object, and set a deleter that calls `factory->deleteObject(ptr)` to
1594 /// destroy the managed object when invoked (e.g., when this managed
1595 /// pointer object is destroyed), unless `0 == ptr`, in which case reset
1596 /// this managed pointer to empty. The deleter will invoke the
1597 /// destructor of `MANAGED_TYPE` rather than the destructor of
1598 /// `TARGET_TYPE`. This function will not compile unless
1599 /// `MANAGED_TYPE *` is convertible to `TARGET_TYPE *`. The behavior is
1600 /// undefined unless the managed object (if any) can be destroyed by the
1601 /// specified `factory`, or if `0 == factory && 0 != ptr`, or if the
1602 /// the lifetime of the managed object is already managed by another
1603 /// object. Note that `bslma::Allocator`, and any class publicly and
1604 /// unambiguously derived from `bslma::Allocator`, meets the
1605 /// requirements for `FACTORY_TYPE`.
1606 template <class MANAGED_TYPE, class FACTORY_TYPE>
1607 void load(MANAGED_TYPE *ptr, FACTORY_TYPE *factory);
1608
1609 /// Destroy the currently managed object, if any. Then, set the target
1610 /// object of this managed pointer to be that referenced by the
1611 /// specified `ptr`, take ownership of `*ptr` as the currently managed
1612 /// object, and set a deleter that will invoke the specified `deleter`
1613 /// with the address of the currently managed object, and with the
1614 /// specified `cookie` (that the deleter can use for its own purposes),
1615 /// unless `0 == ptr`, in which case reset this managed pointer to
1616 /// empty. The behavior is undefined if `ptr` is already managed by
1617 /// another object, or if `0 == deleter && 0 != ptr`. Note that GCC 3.4
1618 /// and earlier versions have a bug in template type deduction/overload
1619 /// resolution that causes ambiguities if this signature is available.
1620 /// This function will be restored on that platform once the deprecated
1621 /// signatures are finally removed.
1622 template <class MANAGED_TYPE>
1623 void load(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1624
1625 /// Destroy the current managed object (if any) and reset this managed
1626 /// pointer to empty. Note that the optionally specified `cookie` and
1627 /// `deleter` will be ignored, as empty managed pointers do not invoke a
1628 /// deleter.
1629 void load(bsl::nullptr_t = 0, void *cookie = 0, DeleterFunc deleter = 0);
1630
1631#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1632 template <class MANAGED_TYPE, class COOKIE_TYPE>
1633 void load(MANAGED_TYPE *ptr, COOKIE_TYPE *cookie, DeleterFunc deleter);
1634
1635 template <class MANAGED_TYPE, class MANAGED_BASE>
1636 void load(MANAGED_TYPE *ptr,
1637 void *cookie,
1638 void (*deleter)(MANAGED_BASE *, void *));
1639
1640 /// [**DEPRECATED**]: Instead, use:
1641 /// @code
1642 /// template <class MANAGED_TYPE>
1643 /// void load(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter);
1644 /// @endcode
1645 /// Destroy the currently managed object, if any. Then, set the target
1646 /// object of this managed pointer to be that referenced by the
1647 /// specified `ptr`, take ownership of `*ptr` as the currently managed
1648 /// object, and set a deleter that will invoke the specified `deleter`
1649 /// with the address of the currently managed object, and with the
1650 /// specified `cookie` (that the deleter can use for its own purposes),
1651 /// unless `0 == ptr`, in which case reset this managed pointer to
1652 /// empty. The behavior is undefined if `ptr` is already managed by
1653 /// another object, or if `0 == deleter && 0 != ptr`. Note that this
1654 /// function is *deprecated* as it relies on undefined compiler behavior
1655 /// for its implementation, but luckily perform as required for all
1656 /// currently supported platforms; on platforms where the non-deprecated
1657 /// overload is not available (e.g., GCC 3.4) code should be written as
1658 /// if it were available, as an appropriate (deprecated) overload will
1659 /// be selected with the correct (non-deprecated) behavior.
1660 template <class MANAGED_TYPE,
1661 class MANAGED_BASE,
1662 class COOKIE_TYPE,
1663 class COOKIE_BASE>
1664 void load(MANAGED_TYPE *ptr,
1665 COOKIE_TYPE *cookie,
1666 void (*deleter)(MANAGED_BASE *, COOKIE_BASE *));
1667#endif // BDE_OMIT_INTERNAL_DEPRECATED
1668
1669 /// If the specified `alias` manages the same object as this managed
1670 /// pointer, set the target object of this managed pointer to be that
1671 /// referenced by the specified `ptr`; otherwise, destroy the currently
1672 /// managed object (if any), and if `alias` is empty, reset this managed
1673 /// pointer to empty; otherwise, transfer ownership (and the deleter) of
1674 /// the object managed by `alias`, and set the target object of this
1675 /// managed pointer to be that referenced by `ptr`. The behavior is
1676 /// undefined if `0 == ptr` and `alias` is not empty, or if `0 != ptr`
1677 /// and `alias` is empty, or if `ptr` is already managed by a managed
1678 /// pointer other than `alias`. Note that this establishes a managed
1679 /// pointer where `ptr` aliases `alias`. The managed object for `alias`
1680 /// will ultimately be destroyed, and the destructor for `ptr` is not
1681 /// called directly.
1682 template <class ALIASED_TYPE>
1683 void loadAlias(ManagedPtr<ALIASED_TYPE>& alias, TARGET_TYPE *ptr);
1684
1685 /// Return a raw pointer to the current target object (if any) and the
1686 /// deleter for the currently managed object, and reset this managed
1687 /// pointer to empty. It is undefined behavior to run the returned
1688 /// deleter unless the returned pointer to target object is not null.
1690
1691 /// Load the specified `deleter` for the currently managed object and
1692 /// reset this managed pointer to empty. Return a raw pointer to the
1693 /// target object (if any) managed by this pointer. It is undefined
1694 /// behavior to run the returned deleter unless the returned pointer to
1695 /// target object is not null.
1697
1698 /// Destroy the current managed object (if any) and reset this managed
1699 /// pointer to empty.
1700 void reset();
1701
1702 /// Exchange the value and ownership of this managed pointer with the
1703 /// specified `other` managed pointer.
1704 void swap(ManagedPtr& other);
1705
1706 // ACCESSORS
1707
1708 /// Return a value of "unspecified bool" type that evaluates to `false`
1709 /// if this managed pointer is empty, and `true` otherwise. Note that
1710 /// this conversion operator allows a managed pointer to be used within
1711 /// a conditional context, such as within an `if` or `while` statement,
1712 /// but does *not* allow managed pointers to be compared (e.g., via `<`
1713 /// or `>`). Also note that a superior solution is available in C++11
1714 /// using the `explicit operator bool()` syntax, that removes the need
1715 /// for a special boolean-like type and private equality-comparison
1716 /// operators.
1717 operator BoolType() const;
1718
1719 /// Return a reference to the target object. The behavior is undefined
1720 /// if this managed pointer is empty, or if `TARGET_TYPE` is `void` or
1721 /// `const void`.
1723
1724 /// Return the address of the target object, or 0 if this managed
1725 /// pointer is empty.
1726 TARGET_TYPE *operator->() const;
1727
1728 /// Return a reference to the non-modifiable deleter information
1729 /// associated with this managed pointer. The behavior is undefined if
1730 /// this managed pointer is empty.
1732
1733 /// Return the address of the target object, or 0 if this managed
1734 /// pointer is empty.
1735 TARGET_TYPE *get() const;
1736
1737 /// [**DEPRECATED**]: Use `get` instead.
1738 ///
1739 /// Return the address of the target object, or 0 if this managed
1740 /// pointer is empty.
1741 TARGET_TYPE *ptr() const;
1742};
1743
1744// FREE FUNCTIONS
1745
1746/// Efficiently exchange the values of the specified `a` and `b` objects.
1747/// This function provides the no-throw exception-safety guarantee.
1748template <class TARGET_TYPE>
1750
1751 // =====================
1752 // struct ManagedPtrUtil
1753 // =====================
1754
1755/// This utility class provides a general no-op deleter, which is useful
1756/// when creating managed pointers to stack-allocated objects.
1758
1759 // CLASS METHODS
1760
1761 /// Deleter function that does nothing.
1762 static void noOpDeleter(void *, void *);
1763
1764#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=14
1765
1766 /// Create an object of the (template parameter) `ELEMENT_TYPE` from the
1767 /// specified `args...` arguments, and return a `ManagedPtr` to manage
1768 /// the new object. Use the specified `allocator` to supply memory for
1769 /// the footprint of the new object and implicitly pass `allocator` as
1770 /// the allocator argument to the `ELEMENT_TYPE` constructor if
1771 /// `bslma::UsesBslmaAllocator<ELEMENT_TYPE>::value` is `true`. If
1772 /// `allocator` is a null pointer, the currently installed default
1773 /// allocator is used. Note that compilation will fail unless
1774 /// `allocator` is convertible to either `bslma::Allocator *` or
1775 /// `bsl::allocator<>`.
1776 template <class ELEMENT_TYPE, class... ARGS>
1778 allocateManaged(bslma::Allocator *allocator, ARGS&&... args);
1779 template <class ELEMENT_TYPE, class ALLOCATOR, class... ARGS>
1782 allocateManaged(const ALLOCATOR& allocator, ARGS&&... args);
1783
1784 /// Create an object of the (template parameter) `ELEMENT_TYPE` from the
1785 /// specified `args...` arguments, and return a `ManagedPtr` to manage
1786 /// the new object. Use the currently installed default allocator to
1787 /// supply memory for the footprint of the new object but do *not*
1788 /// implicitly pass the default allocator as the allocator argument to
1789 /// its constructor even if
1790 /// `bslma::UsesBslmaAllocator<ELEMENT_TYPE>::value` is `true`. Note
1791 /// that an allocator may be included in `args`, but see
1792 /// `allocateManaged` for an alternative function that is better suited
1793 /// to creating managed pointers to objects of allocator-aware type.
1794 template <class ELEMENT_TYPE, class... ARGS>
1795 static ManagedPtr<ELEMENT_TYPE> makeManaged(ARGS&&... args);
1796
1797#endif
1798};
1799
1800 // ===========================
1801 // struct ManagedPtrNilDeleter
1802 // ===========================
1803
1804/// [**DEPRECATED**]: Use `ManagedPtrUtil::noOpDeleter` instead.
1805///
1806/// This utility class provides a general no-op deleter, which is useful
1807/// when creating managed pointers to stack-allocated objects. Note that
1808/// the non-template class `ManagedPtrUtil` should be used in preference to
1809/// this deprecated class, avoiding both template bloat and undefined
1810/// behavior.
1811template <class TARGET_TYPE>
1813
1814 // CLASS METHODS
1815
1816 /// Deleter function that does nothing.
1817 static void deleter(void *, void *);
1818};
1819
1820 // ===========================================
1821 // private class ManagedPtr_FactoryDeleterType
1822 // ===========================================
1823
1824/// This metafunction class-template provides a means to compute the
1825/// preferred deleter function for a factory class for those methods of
1826/// `ManagedPtr` that supply only a factory, and no additional deleter
1827/// function. The intent is to use a common deleter function for all
1828/// allocators that implement the `bslma::Allocator` protocol, rather than
1829/// create a special deleter function based on the complete type of each
1830/// allocator, each doing the same thing (invoking the virtual function
1831/// `deleteObject`).
1832template <class TARGET_TYPE, class FACTORY_TYPE>
1835 bsl::is_convertible<FACTORY_TYPE *, Allocator *>::value,
1836 ManagedPtr_FactoryDeleter<TARGET_TYPE, Allocator>,
1837 ManagedPtr_FactoryDeleter<TARGET_TYPE, FACTORY_TYPE> > {
1838};
1839
1840 // ========================================
1841 // private struct ManagedPtr_DefaultDeleter
1842 // ========================================
1843
1844/// This `struct` provides a function-like managed pointer deleter that
1845/// invokes `delete` with the passed pointer.
1846template <class MANAGED_TYPE>
1848
1849 // CLASS METHODS
1850
1851 /// Cast the specified `ptr` to (template parameter) type
1852 /// `MANAGED_TYPE *`, and then call `delete` with the cast pointer.
1853 static void deleter(void *ptr, void *);
1854};
1855
1856
1857// ============================================================================
1858// INLINE DEFINITIONS
1859// ============================================================================
1860
1861 // ---------------------------------
1862 // private struct ManagedPtr_ImpUtil
1863 // ---------------------------------
1864
1865// CLASS METHODS
1866template <class TYPE>
1867inline
1869{
1870 return static_cast<void *>(
1871 const_cast<typename bsl::remove_cv<TYPE>::type *>(address));
1872}
1873
1874template <class TYPE>
1875inline
1876TYPE *ManagedPtr_ImpUtil::unqualify(const volatile TYPE *address)
1878{
1879 return const_cast<TYPE *>(address);
1880}
1881
1882 // ----------------------------
1883 // private class ManagedPtr_Ref
1884 // ----------------------------
1885
1886// CREATORS
1887template <class TARGET_TYPE>
1888inline
1890 TARGET_TYPE *target)
1891: d_base_p(base)
1892, d_cast_p(target)
1893{
1894 BSLS_ASSERT_SAFE(0 != base);
1895}
1896
1897template <class TARGET_TYPE>
1898inline
1903
1904// ACCESSORS
1905template <class TARGET_TYPE>
1906inline
1908{
1909 return d_base_p;
1910}
1911
1912template <class TARGET_TYPE>
1913inline
1915{
1916 return d_cast_p;
1917}
1918
1919 // ----------------
1920 // class ManagedPtr
1921 // ----------------
1922
1923template <class TARGET_TYPE>
1924class ManagedPtr<volatile TARGET_TYPE>;
1925 // This specialization is declared but not defined, in order to provide an
1926 // early compile-fail check to catch misuse of managed pointer to
1927 // 'volatile' types, which is explicitly called out as not supported in the
1928 // primary class template contract.
1929
1930template <class TARGET_TYPE>
1931class ManagedPtr<TARGET_TYPE&>;
1932 // This specialization is declared but not defined, in order to provide an
1933 // early compile-fail check to catch misuse of managed pointer to reference
1934 // types, which is explicitly called out as not supported in the primary
1935 // class template contract.
1936
1937#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
1938template <class TARGET_TYPE>
1939class ManagedPtr<TARGET_TYPE&&>;
1940 // This specialization is declared but not defined, in order to provide an
1941 // early compile-fail check to catch misuse of managed pointer to reference
1942 // types, which is explicitly called out as not supported in the primary
1943 // class template contract.
1944#endif
1945
1946// PRIVATE CLASS METHODS
1947template <class TARGET_TYPE>
1948inline
1950{
1951 return const_cast<void *>(static_cast<const void *>(ptr));
1952}
1953
1954template <class TARGET_TYPE>
1955template <class MANAGED_TYPE>
1956inline
1957void *
1958ManagedPtr<TARGET_TYPE>::stripCompletePointerType(MANAGED_TYPE *ptr)
1959{
1960 return const_cast<void *>(static_cast<const void *>(ptr));
1961}
1962
1963// PRIVATE MANIPULATORS
1964template <class TARGET_TYPE>
1965template <class MANAGED_TYPE>
1966inline
1967void ManagedPtr<TARGET_TYPE>::loadImp(MANAGED_TYPE *ptr,
1968 void *cookie,
1969 DeleterFunc deleter)
1970{
1972 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
1973
1974 d_members.runDeleter();
1975 d_members.set(stripCompletePointerType(ptr), cookie, deleter);
1976 d_members.setAliasPtr(stripBasePointerType(ptr));
1977}
1978
1979// CREATORS
1980template <class TARGET_TYPE>
1981inline
1983: d_members()
1984{
1985}
1986
1987template <class TARGET_TYPE>
1988template <class MANAGED_TYPE>
1989inline
1991: d_members(stripCompletePointerType(ptr),
1992 0,
1993 &ManagedPtr_DefaultDeleter<MANAGED_TYPE>::deleter,
1994 stripBasePointerType(ptr))
1995{
1997}
1998
1999template <class TARGET_TYPE>
2000inline
2003: d_members(*ref.base())
2004{
2005 d_members.setAliasPtr(stripBasePointerType(ref.target()));
2006}
2007
2008template <class TARGET_TYPE>
2009inline
2011: d_members(original.d_members)
2012{
2013}
2014
2015template <class TARGET_TYPE>
2016inline
2019: d_members(MoveUtil::access(original).d_members)
2020{
2021}
2022
2023#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
2024 template <class TARGET_TYPE>
2025 template <class BDE_OTHER_TYPE>
2026 inline
2028 ManagedPtr<BDE_OTHER_TYPE> &&original,
2029 typename bsl::enable_if<bsl::is_convertible<BDE_OTHER_TYPE *,
2030 TARGET_TYPE *>::value,
2033 : d_members(original.d_members)
2034#elif defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
2035 // sun compiler version 12.3 and earlier
2036 template <class TARGET_TYPE>
2037 template <class BDE_OTHER_TYPE>
2038 inline
2042 : d_members(MoveUtil::access(original).d_members)
2043#else // c++03 except old (version <= 12.3) sun compilers
2044 template <class TARGET_TYPE>
2045 template <class BDE_OTHER_TYPE>
2046 inline
2049 typename bsl::enable_if<bsl::is_convertible<BDE_OTHER_TYPE *,
2050 TARGET_TYPE *>::value,
2053 : d_members(MoveUtil::access(original).d_members)
2054#endif
2055{
2056 // This constructor cannot be constrained using a type trait on old Sun
2057 // compilers (version <= 12.3), so we need the check here.
2058 #if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
2059 BSLMF_ASSERT((bsl::is_convertible<BDE_OTHER_TYPE *,
2060 TARGET_TYPE *>::value));
2061 #endif
2062
2063 // To deal with the possibility of multiple inheritance, we need to
2064 // "correct" the target pointer.
2065 d_members.setAliasPtr(
2066 stripBasePointerType(
2067 static_cast<TARGET_TYPE *>(
2068 static_cast<BDE_OTHER_TYPE *>(
2069 d_members.pointer()))));
2070}
2071
2072
2073template <class TARGET_TYPE>
2074template <class ALIASED_TYPE>
2075inline
2077 TARGET_TYPE *ptr)
2078: d_members()
2079{
2080 BSLS_ASSERT_SAFE(0 != alias.get() || 0 == ptr);
2081
2082 if (0 != ptr) {
2083 d_members.move(&alias.d_members);
2084 d_members.setAliasPtr(stripBasePointerType(ptr));
2085 }
2086}
2087
2088template <class TARGET_TYPE>
2089template <class ALIASED_TYPE>
2090inline
2092#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
2094#else
2096#endif
2097 TARGET_TYPE *ptr)
2098: d_members()
2099{
2100 ManagedPtr<ALIASED_TYPE>& lvalue = alias;
2101
2102 BSLS_ASSERT_SAFE(0 != lvalue.get() || 0 == ptr);
2103
2104 if (0 != ptr) {
2105 d_members.move(&lvalue.d_members);
2106 d_members.setAliasPtr(stripBasePointerType(ptr));
2107 }
2108}
2109
2110template <class TARGET_TYPE>
2111template <class MANAGED_TYPE, class FACTORY_TYPE>
2112inline
2113ManagedPtr<TARGET_TYPE>::ManagedPtr(MANAGED_TYPE *ptr, FACTORY_TYPE *factory)
2114: d_members(stripCompletePointerType(ptr),
2115 factory,
2116 &ManagedPtr_FactoryDeleterType<MANAGED_TYPE,
2117 FACTORY_TYPE>::type::deleter,
2118 stripBasePointerType(ptr))
2119{
2121 BSLS_ASSERT_SAFE(0 != factory || 0 == ptr);
2122}
2123
2124template <class TARGET_TYPE>
2125inline
2130
2131template <class TARGET_TYPE>
2132template <class FACTORY_TYPE>
2133inline
2135: d_members()
2136{
2137}
2138
2139template <class TARGET_TYPE>
2140inline
2142 void *cookie,
2143 DeleterFunc deleter)
2144: d_members(stripBasePointerType(ptr), cookie, deleter)
2145{
2146 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2147}
2148
2149template <class TARGET_TYPE>
2150template <class MANAGED_TYPE>
2151inline
2153 void *cookie,
2154 DeleterFunc deleter)
2155: d_members(stripCompletePointerType(ptr),
2156 cookie,
2157 deleter,
2158 stripBasePointerType(ptr))
2159{
2161
2162 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2163}
2164
2165#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2166template <class TARGET_TYPE>
2167template <class MANAGED_TYPE, class MANAGED_BASE>
2168inline
2170 MANAGED_TYPE *ptr,
2171 void *cookie,
2172 void (*deleter)(MANAGED_BASE *, void *))
2173: d_members(stripCompletePointerType(ptr),
2174 cookie,
2175 reinterpret_cast<DeleterFunc>(deleter),
2176 stripBasePointerType(ptr))
2177{
2179 BSLMF_ASSERT((bsl::is_convertible<MANAGED_TYPE *,
2180 const MANAGED_BASE *>::value));
2181
2182 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2183}
2184
2185template <class TARGET_TYPE>
2186template <class MANAGED_TYPE,
2187 class MANAGED_BASE,
2188 class COOKIE_TYPE,
2189 class COOKIE_BASE>
2190inline
2192 MANAGED_TYPE *ptr,
2193 COOKIE_TYPE *cookie,
2194 void (*deleter)(MANAGED_BASE *, COOKIE_BASE *))
2195: d_members(stripCompletePointerType(ptr),
2196 static_cast<COOKIE_BASE *>(cookie),
2197 reinterpret_cast<DeleterFunc>(deleter),
2198 stripBasePointerType(ptr))
2199{
2201 BSLMF_ASSERT((bsl::is_convertible<MANAGED_TYPE *,
2202 const MANAGED_BASE *>::value));
2204
2205 // Note that the undefined behavior embodied in the @ref reinterpret_cast
2206 // above could be removed by inserting an additional forwarding function
2207 // truly of type 'DeleterFunc' which @ref reinterpret_cast s each pointer
2208 // argument as part of its forwarding behavior. We choose not to do this
2209 // on the grounds of simple efficiency, and there is currently no known
2210 // supported compiler that we use where this does not work as desired.
2211
2212 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2213}
2214#endif // BDE_OMIT_INTERNAL_DEPRECATED
2215
2216template <class TARGET_TYPE>
2217inline
2219{
2220 d_members.runDeleter();
2221}
2222
2223// MANIPULATORS
2224template <class TARGET_TYPE>
2225inline
2228{
2229 d_members.moveAssign(&rhs.d_members);
2230 return *this;
2231}
2232
2233template <class TARGET_TYPE>
2234inline
2238{
2239 ManagedPtr& lvalue = rhs;
2240 d_members.moveAssign(&lvalue.d_members);
2241 return *this;
2242}
2243
2244#if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES)
2245 template <class TARGET_TYPE>
2246 template <class BDE_OTHER_TYPE>
2247 inline
2248 typename bsl::enable_if<
2253#elif defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
2254 // sun compiler version 12.3 and earlier
2255 template <class TARGET_TYPE>
2256 template <class BDE_OTHER_TYPE>
2257 inline
2262#else // c++03 except old (version <= 12.3) sun compilers
2263 template <class TARGET_TYPE>
2264 template <class BDE_OTHER_TYPE>
2265 inline
2266 typename bsl::enable_if<
2272#endif
2273{
2274 // This operator cannot be constrained using a type trait on Sun, so we
2275 // need the check here.
2276 #if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
2277 BSLMF_ASSERT((bsl::is_convertible<BDE_OTHER_TYPE *,
2278 TARGET_TYPE *>::value));
2279 #endif
2280
2281 ManagedPtr<BDE_OTHER_TYPE>& lvalue = rhs;
2282 d_members.moveAssign(&lvalue.d_members);
2283
2284 // To deal with the possibility of multiple inheritance, we need to
2285 // "correct" the target pointer.
2286 d_members.setAliasPtr(
2287 stripBasePointerType(
2288 static_cast<TARGET_TYPE *>(
2289 static_cast<BDE_OTHER_TYPE *>(
2290 d_members.pointer()))));
2291
2292 return *this;
2293}
2294
2295template <class TARGET_TYPE>
2296inline
2300{
2301 d_members.moveAssign(ref.base());
2302 d_members.setAliasPtr(stripBasePointerType(ref.target()));
2303 return *this;
2304}
2305
2306template <class TARGET_TYPE>
2307inline
2310{
2311 this->reset();
2312 return *this;
2313}
2314
2315template <class TARGET_TYPE>
2316template <class REFERENCED_TYPE>
2317inline
2319{
2320 BSLMF_ASSERT((bsl::is_convertible<TARGET_TYPE *,
2321 REFERENCED_TYPE *>::value));
2322
2323 return ManagedPtr_Ref<REFERENCED_TYPE>(&d_members,
2324 static_cast<REFERENCED_TYPE *>(
2325 static_cast<TARGET_TYPE *>(d_members.pointer())));
2326}
2327
2328template <class TARGET_TYPE>
2329inline
2331{
2332 reset();
2333}
2334
2335template <class TARGET_TYPE>
2336template <class MANAGED_TYPE>
2337inline
2338void ManagedPtr<TARGET_TYPE>::load(MANAGED_TYPE *ptr)
2339{
2341
2343 this->loadImp(ptr,
2344 static_cast<void *>(Default::allocator()),
2345 &DeleterFactory::deleter);
2346}
2347
2348template <class TARGET_TYPE>
2349template <class MANAGED_TYPE, class FACTORY_TYPE>
2350inline
2351void ManagedPtr<TARGET_TYPE>::load(MANAGED_TYPE *ptr, FACTORY_TYPE *factory)
2352{
2354 BSLS_ASSERT_SAFE(0 != factory || 0 == ptr);
2355
2356 typedef typename
2358 DeleterFactory;
2359
2360 this->loadImp(ptr, static_cast<void *>(factory), &DeleterFactory::deleter);
2361}
2362
2363template <class TARGET_TYPE>
2364template <class MANAGED_TYPE>
2365inline
2366void ManagedPtr<TARGET_TYPE>::load(MANAGED_TYPE *ptr,
2367 void *cookie,
2368 DeleterFunc deleter)
2369{
2371 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2372
2373 this->loadImp(ptr, cookie, deleter);
2374}
2375
2376template <class TARGET_TYPE>
2377inline
2379{
2380 this->reset();
2381}
2382
2383#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2384template <class TARGET_TYPE>
2385template <class MANAGED_TYPE, class COOKIE_TYPE>
2386inline
2387void ManagedPtr<TARGET_TYPE>::load(MANAGED_TYPE *ptr,
2388 COOKIE_TYPE *cookie,
2389 DeleterFunc deleter)
2390{
2392 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2393
2394 this->loadImp(ptr, static_cast<void *>(cookie), deleter);
2395}
2396
2397template <class TARGET_TYPE>
2398template <class MANAGED_TYPE, class MANAGED_BASE>
2399inline
2401 MANAGED_TYPE *ptr,
2402 void *cookie,
2403 void (*deleter)(MANAGED_BASE *, void *))
2404{
2408 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2409
2410 this->loadImp(ptr, cookie, reinterpret_cast<DeleterFunc>(deleter));
2411}
2412
2413template <class TARGET_TYPE>
2414template <class MANAGED_TYPE,
2415 class MANAGED_BASE,
2416 class COOKIE_TYPE,
2417 class COOKIE_BASE>
2418inline
2420 MANAGED_TYPE *ptr,
2421 COOKIE_TYPE *cookie,
2422 void (*deleter)(MANAGED_BASE *, COOKIE_BASE *))
2423{
2427 BSLS_ASSERT_SAFE(0 != deleter || 0 == ptr);
2428
2429 this->loadImp(ptr,
2430 static_cast<void *>(static_cast<COOKIE_BASE *>(cookie)),
2431 reinterpret_cast<DeleterFunc>(deleter));
2432}
2433#endif // BDE_OMIT_INTERNAL_DEPRECATED
2434
2435template <class TARGET_TYPE>
2436template <class ALIASED_TYPE>
2438 TARGET_TYPE *ptr)
2439{
2440 BSLS_ASSERT_SAFE(!ptr == !alias.get()); // both null or both non-null
2441
2442 if (ptr && alias.d_members.pointer()) {
2443 d_members.moveAssign(&alias.d_members);
2444 d_members.setAliasPtr(stripBasePointerType(ptr));
2445 }
2446 else {
2447 d_members.runDeleter();
2448 d_members.clear();
2449 }
2450}
2451
2452template <class TARGET_TYPE>
2455{
2457
2458 TARGET_TYPE *p = get();
2459
2460 // The behavior would be undefined if 'd_members.deleter()' were called
2461 // when 'p' is null.
2462
2463 if (p) {
2464 ResultType result = { p, d_members.deleter() };
2465 d_members.clear();
2466 return result; // RETURN
2467 }
2468 ResultType result = { p, ManagedPtrDeleter() };
2469 return result;
2470}
2471
2472template <class TARGET_TYPE>
2474{
2475 BSLS_ASSERT_SAFE(deleter);
2476
2477 TARGET_TYPE *result = get();
2478
2479 // The behavior is undefined if 'd_members.deleter()' is called when
2480 // 'result' is null.
2481
2482 if (result) {
2483 *deleter = d_members.deleter();
2484 d_members.clear();
2485 }
2486 return result;
2487}
2488
2489template <class TARGET_TYPE>
2490inline
2492{
2493 d_members.runDeleter();
2494 d_members.clear();
2495}
2496
2497template <class TARGET_TYPE>
2498inline
2500{
2501 d_members.swap(other.d_members);
2502}
2503
2504// ACCESSORS
2505template <class TARGET_TYPE>
2506inline
2507#if defined(BSLS_PLATFORM_CMP_IBM) // last confirmed with xlC 12.1
2508ManagedPtr<TARGET_TYPE>::operator typename ManagedPtr::BoolType() const
2509#else
2511#endif
2512{
2513 return d_members.pointer()
2516}
2517
2518template <class TARGET_TYPE>
2519inline
2522{
2523 BSLS_ASSERT_SAFE(d_members.pointer());
2524
2525 return *static_cast<TARGET_TYPE *>(d_members.pointer());
2526}
2527
2528template <class TARGET_TYPE>
2529inline
2531{
2532 return static_cast<TARGET_TYPE *>(d_members.pointer());
2533}
2534
2535template <class TARGET_TYPE>
2536inline
2538{
2539 BSLS_ASSERT_SAFE(d_members.pointer());
2540
2541 return d_members.deleter();
2542}
2543
2544template <class TARGET_TYPE>
2545inline
2547{
2548 return static_cast<TARGET_TYPE *>(d_members.pointer());
2549}
2550
2551template <class TARGET_TYPE>
2552inline
2554{
2555 return get();
2556}
2557
2558// FREE FUNCTIONS
2559template <class TARGET_TYPE>
2560inline
2562{
2563 a.swap(b);
2564}
2565
2566 // --------------------
2567 // class ManagedPtrUtil
2568 // --------------------
2569
2570#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=14
2571
2572template <class ELEMENT_TYPE, class ALLOCATOR, class... ARGS>
2573inline
2575 ManagedPtr<ELEMENT_TYPE> >::type
2576ManagedPtrUtil::allocateManaged(const ALLOCATOR& allocator, ARGS&&... args)
2577{
2578 return allocateManaged<ELEMENT_TYPE>(
2579 allocator.mechanism(),
2580 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
2581}
2582
2583template <class ELEMENT_TYPE, class... ARGS>
2584inline
2586{
2588
2589 typedef typename bsl::remove_cv<ELEMENT_TYPE>::type UnqualElem;
2590
2591 // Use 'allocateObject' with a separate construction step to avoid passing
2592 // the allocator to the constructed object.
2593 UnqualElem *objPtr =
2594 bslma::AllocatorUtil::allocateObject<UnqualElem>(defaultAllocator);
2595
2597 defaultAllocator, objPtr);
2598
2599 // Do not pass an allocator to the element constructor.
2600 ::new (ManagedPtr_ImpUtil::voidify(objPtr)) ELEMENT_TYPE(
2601 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
2602 proctor.release();
2603
2604 return ManagedPtr<ELEMENT_TYPE>(objPtr, defaultAllocator);
2605}
2606
2607template <class ELEMENT_TYPE, class... ARGS>
2608inline
2611{
2612 typedef typename bsl::remove_cv<ELEMENT_TYPE>::type UnqualElem;
2613
2614 allocator = bslma::Default::allocator(allocator);
2615
2616 ELEMENT_TYPE *objPtr = bslma::AllocatorUtil::newObject<UnqualElem>(
2617 allocator,
2618 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
2619
2620 return ManagedPtr<ELEMENT_TYPE>(objPtr, allocator);
2621}
2622
2623#endif
2624
2625 // --------------------------
2626 // class ManagedPtrNilDeleter
2627 // --------------------------
2628
2629// CLASS METHODS
2630template <class TARGET_TYPE>
2631inline
2633{
2634}
2635
2636 // ----------------------------------------
2637 // private struct ManagedPtr_DefaultDeleter
2638 // ----------------------------------------
2639
2640// CLASS METHODS
2641template <class MANAGED_TYPE>
2642inline
2644{
2645 delete reinterpret_cast<MANAGED_TYPE *>(ptr);
2646}
2647
2648} // close package namespace
2649
2650// ============================================================================
2651// TYPE TRAITS
2652// ============================================================================
2653
2654namespace bslmf {
2655
2656template <class TARGET_TYPE>
2657struct HasPointerSemantics<bslma::ManagedPtr<TARGET_TYPE> > : bsl::true_type
2658{
2659};
2660
2661template <class TARGET_TYPE>
2662struct IsBitwiseMoveable<bslma::ManagedPtr<TARGET_TYPE> > : bsl::true_type
2663{
2664};
2665
2666} // close namespace bslmf
2667
2668
2669namespace bsl {
2670
2671template <class TARGET_TYPE>
2673 BloombergLP::bslma::ManagedPtr<TARGET_TYPE> > : bsl::true_type
2674{
2675};
2676
2677} // close namespace bsl
2678
2679#endif // End C++11 code
2680
2681#endif
2682
2683// ----------------------------------------------------------------------------
2684// Copyright 2016 Bloomberg Finance L.P.
2685//
2686// Licensed under the Apache License, Version 2.0 (the "License");
2687// you may not use this file except in compliance with the License.
2688// You may obtain a copy of the License at
2689//
2690// http://www.apache.org/licenses/LICENSE-2.0
2691//
2692// Unless required by applicable law or agreed to in writing, software
2693// distributed under the License is distributed on an "AS IS" BASIS,
2694// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2695// See the License for the specific language governing permissions and
2696// limitations under the License.
2697// ----------------------------- END-OF-FILE ----------------------------------
2698
2699/** @} */
2700/** @} */
2701/** @} */
Definition bslma_allocator.h:457
Definition bslma_deallocateobjectproctor.h:273
PtrType release()
Definition bslma_deallocateobjectproctor.h:438
Definition bslma_managedptrdeleter.h:109
void(* Deleter)(void *managedObject, void *cookie)
Deleter function prototype used to destroy the managed pointer.
Definition bslma_managedptrdeleter.h:115
Deleter deleter() const
Return the deleter function associated with this deleter.
Definition bslma_managedptrdeleter.h:255
Definition bslma_managedptr_members.h:86
void setAliasPtr(void *alias)
Definition bslma_managedptr_members.h:297
void runDeleter() const
Definition bslma_managedptr_members.h:320
void set(void *object, void *factory, DeleterFunc deleter)
Definition bslma_managedptr_members.h:283
void * pointer() const
Definition bslma_managedptr_members.h:314
Definition bslma_managedptr.h:1105
ManagedPtr_Ref(const ManagedPtr_Ref &original)=default
~ManagedPtr_Ref()
Definition bslma_managedptr.h:1899
ManagedPtr_Ref & operator=(const ManagedPtr_Ref &original)=default
TARGET_TYPE * target() const
Return a pointer to the referenced object.
Definition bslma_managedptr.h:1914
ManagedPtr_Ref(ManagedPtr_Members *base, TARGET_TYPE *target)
Definition bslma_managedptr.h:1889
ManagedPtr_Members * base() const
Return a pointer to the managed state of a ManagedPtr object.
Definition bslma_managedptr.h:1907
Definition bslma_managedptr.h:1182
ManagedPtr(TARGET_TYPE *ptr, void *cookie, DeleterFunc deleter)
Definition bslma_managedptr.h:2141
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:2047
TARGET_TYPE * get() const
Definition bslma_managedptr.h:2546
void load(bsl::nullptr_t=0, void *cookie=0, DeleterFunc deleter=0)
Definition bslma_managedptr.h:2378
void load(MANAGED_TYPE *ptr, FACTORY_TYPE *factory)
Definition bslma_managedptr.h:2351
TARGET_TYPE * release(ManagedPtrDeleter *deleter)
Definition bslma_managedptr.h:2473
ManagedPtr(ManagedPtr< ALIASED_TYPE > &alias, TARGET_TYPE *ptr)
Definition bslma_managedptr.h:2076
ManagedPtr(bsl::nullptr_t, FACTORY_TYPE *factory)
Definition bslma_managedptr.h:2134
ManagedPtr(MANAGED_TYPE *ptr, COOKIE_TYPE *cookie, void(*deleter)(MANAGED_BASE *, COOKIE_BASE *))
Definition bslma_managedptr.h:2191
TARGET_TYPE * ptr() const
Definition bslma_managedptr.h:2553
~ManagedPtr()
Definition bslma_managedptr.h:2218
bslmf::AddReference< TARGET_TYPE >::Type operator*() const
Definition bslma_managedptr.h:2521
const ManagedPtrDeleter & deleter() const
Definition bslma_managedptr.h:2537
ManagedPtr & operator=(ManagedPtr_Ref< TARGET_TYPE > ref) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2298
ManagedPtr(MANAGED_TYPE *ptr)
Definition bslma_managedptr.h:1990
void load(MANAGED_TYPE *ptr, COOKIE_TYPE *cookie, void(*deleter)(MANAGED_BASE *, COOKIE_BASE *))
Definition bslma_managedptr.h:2419
void swap(ManagedPtr &other)
Definition bslma_managedptr.h:2499
void load(MANAGED_TYPE *ptr)
Definition bslma_managedptr.h:2338
ManagedPtr & operator=(bslmf::MovableRef< ManagedPtr > rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2236
ManagedPtr(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter)
Definition bslma_managedptr.h:2152
ManagedPtr()
Create an empty managed pointer.
Definition bslma_managedptr.h:1982
void load(MANAGED_TYPE *ptr, void *cookie, DeleterFunc deleter)
Definition bslma_managedptr.h:2366
ManagedPtr(MANAGED_TYPE *ptr, FACTORY_TYPE *factory)
Definition bslma_managedptr.h:2113
void load(MANAGED_TYPE *ptr, COOKIE_TYPE *cookie, DeleterFunc deleter)
Definition bslma_managedptr.h:2387
ManagedPtr & operator=(bsl::nullptr_t)
Definition bslma_managedptr.h:2309
void load(MANAGED_TYPE *ptr, void *cookie, void(*deleter)(MANAGED_BASE *, void *))
Definition bslma_managedptr.h:2400
ManagedPtr(MANAGED_TYPE *ptr, void *cookie, void(*deleter)(MANAGED_BASE *, void *))
Definition bslma_managedptr.h:2169
TARGET_TYPE * operator->() const
Definition bslma_managedptr.h:2530
ManagedPtr(bslmf::MovableRef< ManagedPtr > original) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2017
void clear()
Definition bslma_managedptr.h:2330
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:2269
ManagedPtr & operator=(ManagedPtr &rhs) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2227
TARGET_TYPE element_type
Alias to the TARGET_TYPE template parameter.
Definition bslma_managedptr.h:1192
ManagedPtr(bslmf::MovableRef< ManagedPtr< ALIASED_TYPE > > alias, TARGET_TYPE *ptr)
Definition bslma_managedptr.h:2091
ManagedPtr_PairProxy< TARGET_TYPE, ManagedPtrDeleter > release()
Definition bslma_managedptr.h:2454
ManagedPtr(ManagedPtr_Ref< TARGET_TYPE > ref) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2001
ManagedPtr(bsl::nullptr_t, bsl::nullptr_t=0)
Definition bslma_managedptr.h:2126
friend class ManagedPtr
Definition bslma_managedptr.h:1288
ManagedPtr(ManagedPtr &original) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:2010
void reset()
Definition bslma_managedptr.h:2491
void loadAlias(ManagedPtr< ALIASED_TYPE > &alias, TARGET_TYPE *ptr)
Definition bslma_managedptr.h:2437
ManagedPtrDeleter::Deleter DeleterFunc
Definition bslma_managedptr.h:1189
Definition bslmf_movableref.h:751
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:229
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2018
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
Definition bdlb_printmethods.h:283
BloombergLP::bsls::Nullptr_Impl::Type nullptr_t
Definition bsls_nullptr.h:281
Definition balxml_encoderoptions.h:68
Definition bdlbb_blob.h:576
Definition bslmf_conditional.h:120
Definition bslmf_enableif.h:525
Definition bslmf_isconvertible.h:867
Definition bslmf_isnothrowmoveconstructible.h:358
Definition bslmf_isvoid.h:138
remove_const< typenameremove_volatile< t_TYPE >::type >::type type
Definition bslmf_removecv.h:126
static Allocator * allocator(Allocator *basicAllocator=0)
Definition bslma_default.h:897
static Allocator * defaultAllocator()
Definition bslma_default.h:889
Definition bslma_managedptr.h:1812
static void deleter(void *, void *)
Deleter function that does nothing.
Definition bslma_managedptr.h:2632
Definition bslma_managedptr.h:1757
static ManagedPtr< ELEMENT_TYPE > makeManaged(ARGS &&... args)
Definition bslma_managedptr.h:2585
static ManagedPtr< ELEMENT_TYPE > allocateManaged(bslma::Allocator *allocator, ARGS &&... args)
Definition bslma_managedptr.h:2610
static void noOpDeleter(void *, void *)
Deleter function that does nothing.
Definition bslma_managedptr.h:1847
static void deleter(void *ptr, void *)
Definition bslma_managedptr.h:2643
Definition bslma_managedptr.h:1837
Definition bslma_managedptr_factorydeleter.h:71
Definition bslma_managedptr.h:1073
static void * voidify(TYPE *address) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:1868
static TYPE * unqualify(const volatile TYPE *address) BSLS_KEYWORD_NOEXCEPT
Definition bslma_managedptr.h:1876
Definition bslma_managedptr_pairproxy.h:80
Definition bslma_managedptr.h:1153
bsl::add_lvalue_reference< t_TYPE >::type Type
Definition bslmf_addreference.h:188
Definition bslmf_haspointersemantics.h:78
Definition bslmf_isbitwisemoveable.h:718
Definition bslmf_movableref.h:791