BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslma_constructionutil.h
Go to the documentation of this file.
1/// @file bslma_constructionutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_constructionutil.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_CONSTRUCTIONUTIL
9#define INCLUDED_BSLMA_CONSTRUCTIONUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_constructionutil bslma_constructionutil
15/// @brief Provide methods to construct arbitrarily-typed objects uniformly.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_constructionutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_constructionutil-purpose"> Purpose</a>
25/// * <a href="#bslma_constructionutil-classes"> Classes </a>
26/// * <a href="#bslma_constructionutil-description"> Description </a>
27/// * <a href="#bslma_constructionutil-type-traits"> Type Traits </a>
28/// * <a href="#bslma_constructionutil-usage"> Usage </a>
29/// * <a href="#bslma_constructionutil-example-1-using-bslma-constructionutil-to-implement-a-container"> Example 1: Using bslma::ConstructionUtil to Implement a Container </a>
30/// * <a href="#bslma_constructionutil-example-2-bslma-allocator-propagation"> Example 2: bslma Allocator Propagation </a>
31/// * <a href="#bslma_constructionutil-example-3-constructing-into-non-heap-memory"> Example 3: Constructing into Non-heap Memory </a>
32///
33/// # Purpose {#bslma_constructionutil-purpose}
34/// Provide methods to construct arbitrarily-typed objects uniformly.
35///
36/// # Classes {#bslma_constructionutil-classes}
37///
38/// - bslma::ConstructionUtil: namespace for methods to construct objects
39///
40/// @see bslma_allocator, bslma_bslallocator, bslma_destructionutil
41///
42/// # Description {#bslma_constructionutil-description}
43/// This component provides a `struct`, `bslma::ConstructionUtil`,
44/// that serves as a namespace for utility functions to construct objects of an
45/// arbitrary (template parameter) type, given an allocator and an arbitrary
46/// number of arguments. These functions are useful for uniformly constructing
47/// an object without concern for whether the object's type is allocator-aware
48/// (AA) and, if so, whether the allocator is passed at the end of the argument
49/// list (trailing allocator-argument convention) or at the start of the
50/// argument list, preceeded by `bsl::allocator_arg` (leading allocator-argument
51/// convention). If the type being constructed is not AA or if a non-allocator
52/// scalar such as an `int` or `void *` is passed to these methods, the
53/// allocator argument is discarded and a non-allocator constructor is invoked.
54///
55/// An additional `destructiveMove` method moves an object to a new address and
56/// destroys the object at the original address, often doing so as an efficient
57/// `memcpy` rather than separate move-destroy operations.
58///
59/// *Legacy-AA* (types with constructors having a parameter of type
60/// `bslma::Allocator *`) and *bsl-AA* types (types with constructors having a
61/// parameter of type `bsl::allocator<>`) are handled interchangeably by the
62/// functions in this component, accepting either a `bslma::Allocator*` or a
63/// `bsl::allocator` argument and then passing the appropriate type to the
64/// constructed type. Thus *bsl-AA* code can work seamlessly with *legacy-AA*
65/// code, allowing for a smooth transition from the old model to the new one.
66/// Note that this component does not directly use `bsl::allocator` or
67/// `bsl::polymorphic_allocator` because such use would cause a circular
68/// dependancy; an allocator is considered bsl-like if it is implicitly
69/// convertible from `bslma::Allocator *` and has a `mechanism` method that
70/// returns a `bslma::Allocator *` and an allocator is considered pmr-like if it
71/// is convertible from `bsl::memory_resource *` (and therefore also convertible
72/// from `bslma::Allocator *`.
73///
74/// The `construct` method provided here has roughly the same functionality as
75/// the C++20 library function `std::uninitialized_construct_using_allocator`
76/// and the `make` method has roughly the same functionality as
77/// `std::make_obj_using_allocator`, with the following differences:
78///
79/// * As described above, *Legacy-AA* types are treated as interchangle with
80/// *bsl-AA* types and `bslma::Allocator *` is treated as interchangeable
81/// with `bsl::allocator`.
82/// * The methods in this component accept a non-allocator scalar (e.g., `int`
83/// or `void *`) instead of an allocator to indicate that no allocator should
84/// be supplied to the object constructor, even if it is AA.
85/// * The `std` functions will ignore the allocator if it is incompatible with
86/// the object type being constructed. The methods in this component,
87/// conversely, will ignore the allocator only for *non-AA* and *stl-AA*
88/// types. For *legacy-AA*, *bsl-AA*, and *pmr-AA* types, an incompatible
89/// allocator will result in a compilation failure. This special case exists
90/// to avoid subtle errors in the Bloomberg code base where a bad allocator
91/// argument is used in a situation where allocator propagation is expected.
92/// * This component does not provide special handling for `std::pair`.
93///
94/// ## Type Traits {#bslma_constructionutil-type-traits}
95///
96///
97/// The facilities in this component query several type traits of the `TYPE`
98/// being constructed, using that information as follows:
99/// @code
100/// Trait How Used
101/// --------------------------- -----------------------------------------------
102/// bslma::UsesBslmaAllocator If true, the allocator being passed in must be
103/// either convertible to `bslma::Allocator *` or
104/// else have a `mechanism` accessor. If false,
105/// the allocator argument must be convertible to
106/// the `TYPE::allocator_type`.
107///
108/// bslma::HasAllocatorType If true, `TYPE::allocator_type` is assumed to
109/// the type of allocator accepted by `TYPE`'s
110/// constructors.
111///
112/// bsl::uses_allocator<TYPE,A> If true, then `A` can be used as an allocator
113/// to construct `TYPE`.
114///
115/// bslmf::UsesAllocatorArgT If true, an allocator argument is passed as the
116/// second argument to the constructor, preceeded
117/// by a `bsl::allocator_arg` tag; otherwise the
118/// allocator is passed as the last argument to the
119/// constructor.
120///
121/// bslmf::IsBitwiseMoveable If true, `destructiveMove` is implemented as a
122/// simple `memcpy`, rather than as a move-destroy
123/// sequence.
124/// @endcode
125///
126/// ## Usage {#bslma_constructionutil-usage}
127///
128///
129/// This section illustrates intended use of this component.
130///
131/// ### Example 1: Using bslma::ConstructionUtil to Implement a Container {#bslma_constructionutil-example-1-using-bslma-constructionutil-to-implement-a-container}
132///
133///
134/// This example demonstrates the intended use of `bslma::ConstructionUtil` to
135/// implement a simple container class that uses an instance of `bsl::allocator`
136/// for memory management.
137///
138/// First, because allocation and construction are done in two separate steps,
139/// we need to define a proctor type that will deallocate the allocated memory
140/// in case the constructor throws an exception:
141/// @code
142/// #include <bslma_bslallocator.h>
143///
144/// /// This class implements a proctor to release memory allocated during
145/// /// the construction of a `MyContainer` object if the constructor for
146/// /// the container's data element throws an exception. Such a proctor
147/// /// should be `release`d once the element is safely constructed.
148/// template <class TYPE>
149/// class MyContainerProctor {
150///
151/// // DATA
152/// bsl::allocator<TYPE> d_allocator;
153/// TYPE *d_address_p; // proctored memory
154///
155/// private:
156/// // NOT IMPLEMENTED
157/// MyContainerProctor(const MyContainerProctor&); // = delete
158/// MyContainerProctor& operator=(const MyContainerProctor&); // = delete
159///
160/// public:
161/// // CREATORS
162///
163/// /// Create a proctor that conditionally manages the memory at the
164/// /// specified `address`, and that uses the specified `allocator` to
165/// /// deallocate the block of memory (if not released -- see
166/// /// `release`) upon destruction. The behavior is undefined unless
167/// /// `allocator` is non-zero and supplied the memory at `address`.
168/// MyContainerProctor(const bsl::allocator<TYPE> allocator, TYPE *address)
169/// : d_allocator(allocator)
170/// , d_address_p(address)
171/// {
172/// }
173///
174/// /// Destroy this proctor, and deallocate the block of memory it
175/// /// manages (if any) by invoking the `deallocate` method of the
176/// /// allocator that was supplied at construction of this proctor. If
177/// /// no memory is currently being managed, this method has no effect.
178/// ~MyContainerProctor()
179/// {
180/// if (d_address_p) {
181/// d_allocator.deallocate(d_address_p, 1);
182/// }
183/// }
184///
185/// // MANIPULATORS
186///
187/// /// Release from management the block of memory currently managed by
188/// /// this proctor. If no memory is currently being managed, this
189/// /// method has no effect.
190/// void release()
191/// {
192/// d_address_p = 0;
193/// }
194/// };
195/// @endcode
196/// Then, we create a container class that holds a single element and uses
197/// `bsl::allocator` to supply memory:
198/// @code
199/// #include <bslma_constructionutil.h>
200///
201/// /// This class provides a container that always holds exactly one
202/// /// element, dynamically allocated using the specified `bslma`
203/// /// allocator.
204/// template <class TYPE>
205/// class MyContainer {
206///
207/// // DATA
208/// bsl::allocator<TYPE> d_allocator;
209/// TYPE *d_value_p;
210///
211/// /// Return the address of a new element that was allocated from this
212/// /// container's allocator and initialized with the optionally
213/// /// specified `value`, or default-initialized if `value` is not
214/// /// specified. If `TYPE` is AA, this container's allocator is used
215/// /// to construct the new element.
216/// TYPE *createElement();
217/// TYPE *createElement(const TYPE& value);
218///
219/// public:
220/// typedef bsl::allocator<TYPE> allocator_type;
221///
222/// // CREATORS
223///
224/// /// Create a container with a default-constructed element.
225/// /// Optionally specify a `allocator` used to supply memory.
226/// explicit
227/// MyContainer(const allocator_type& allocator = allocator_type())
228/// : d_allocator(allocator), d_value_p(createElement()) { }
229///
230/// /// Create a container having an element constructed from the
231/// /// specified `value`. Optionally specify an `allocator` to supply
232/// /// memory both for the container and for the contained element.
233/// explicit
234/// MyContainer(const TYPE& value,
235/// const allocator_type& allocator = allocator_type())
236/// : d_allocator(allocator), d_value_p(createElement(value)) { }
237///
238/// /// Create a container having the same value as the specified
239/// /// `original` object. Optionally specify a `allocator` used
240/// /// to supply memory. If `allocator` is 0, the currently
241/// /// installed default allocator is used.
242/// MyContainer(const MyContainer& original,
243/// const allocator_type& allocator = allocator_type())
244/// : d_allocator(allocator)
245/// , d_value_p(createElement(*original.d_value_p)) { }
246///
247/// /// Destroy this object.
248/// ~MyContainer();
249///
250/// // MANIPULATORS
251///
252/// /// Assign to this object the value of the specified `rhs` object,
253/// /// and return a reference providing modifiable access to this
254/// /// object.
255/// MyContainer& operator=(const TYPE& rhs);
256/// MyContainer& operator=(const MyContainer& rhs);
257///
258/// /// Return a non-`const` reference to the element contained in this
259/// /// object.
260/// TYPE& front()
261/// {
262/// return *d_value_p;
263/// }
264///
265/// // ACCESSORS
266///
267/// /// Return a `const` reference to the element contained in this
268/// /// object.
269/// const TYPE& front() const
270/// {
271/// return *d_value_p;
272/// }
273///
274/// /// Return the allocator used by this object to supply memory.
275/// allocator_type get_allocator() const
276/// {
277/// return d_allocator;
278/// }
279///
280/// // etc.
281/// };
282/// @endcode
283/// Next, we implement the private `createElement` members that allocate memory
284/// and construct a `TYPE` object in the allocated memory. We perform the
285/// allocation using the `allocate` method of `bsl::allocator` and the
286/// construction using the `construct` method of `ConstructionUtil` that
287/// provides the correct semantics for passing the allocator to the constructed
288/// object when appropriate:
289/// @code
290/// template <class TYPE>
291/// TYPE *MyContainer<TYPE>::createElement()
292/// {
293/// TYPE *value_p = d_allocator.allocate(1);
294/// MyContainerProctor<TYPE> proctor(d_allocator, value_p);
295///
296/// // Call 'construct' passing the allocator but no constructor
297/// // arguments.
298///
299/// bslma::ConstructionUtil::construct(value_p, d_allocator);
300/// proctor.release();
301///
302/// return value_p;
303/// }
304///
305/// template <class TYPE>
306/// TYPE *MyContainer<TYPE>::createElement(const TYPE& value)
307/// {
308/// TYPE *value_p = d_allocator.allocate(1);
309/// MyContainerProctor<TYPE> proctor(d_allocator, value_p);
310///
311/// // Call 'construct' passing the allocator and 'value' arguments.
312///
313/// bslma::ConstructionUtil::construct(value_p, d_allocator, value);
314/// proctor.release();
315///
316/// return value_p;
317/// }
318/// @endcode
319/// Now, the destructor destroys the object and deallocates the memory used to
320/// hold the element using the allocator:
321/// @code
322/// template <class TYPE>
323/// MyContainer<TYPE>::~MyContainer()
324/// {
325/// d_value_p->~TYPE();
326/// d_allocator.deallocate(d_value_p, 1);
327/// }
328/// @endcode
329/// Next, the assignment operator needs to assign the value without modifying
330/// the allocator.
331/// @code
332/// template <class TYPE>
333/// MyContainer<TYPE>& MyContainer<TYPE>::operator=(const TYPE& rhs)
334/// {
335/// if (&rhs != d_value_p) {
336/// *d_value_p = rhs;
337/// }
338/// return *this;
339/// }
340///
341/// template <class TYPE>
342/// MyContainer<TYPE>& MyContainer<TYPE>::operator=(const MyContainer& rhs)
343/// {
344/// return operator=(*rhs.d_value_p);
345/// }
346/// @endcode
347/// Finally, we perform a simple test of `MyContainer`, instantiating it with
348/// element type `int`:
349/// @code
350/// int main()
351/// {
352/// bslma::TestAllocator testAlloc;
353/// MyContainer<int> C1(123, &testAlloc);
354/// assert(C1.get_allocator() == &testAlloc);
355/// assert(C1.front() == 123);
356///
357/// MyContainer<int> C2(C1);
358/// assert(C2.get_allocator() == bslma::Default::defaultAllocator());
359/// assert(C2.front() == 123);
360///
361/// return 0;
362/// }
363/// @endcode
364///
365/// ### Example 2: bslma Allocator Propagation {#bslma_constructionutil-example-2-bslma-allocator-propagation}
366///
367///
368/// This example demonstrates that `MyContainer` does indeed propagate the
369/// allocator to its contained element.
370///
371/// First, we create a representative element class, `MyType`. Unlike the
372/// `MyContainer` template, `MyType` allocates memory using the
373/// `bslma::Allocator *` (legacy) allocator model instead of the
374/// `bsl::allocator` (bsl) allocator model:
375/// @code
376/// #include <bslma_default.h>
377///
378/// class MyType {
379///
380/// // DATA
381/// bslma::Allocator *d_allocator_p;
382/// int d_value;
383/// // ...
384///
385/// public:
386/// // TRAITS
387/// BSLMF_NESTED_TRAIT_DECLARATION(MyType, bslma::UsesBslmaAllocator);
388///
389/// // CREATORS
390///
391/// /// Create a `MyType` object having the default value. Optionally
392/// /// specify a `basicAllocator` used to supply memory. If
393/// /// `basicAllocator` is 0, the currently installed default allocator
394/// /// is used.
395/// explicit MyType(bslma::Allocator *basicAllocator = 0)
396/// : d_allocator_p(bslma::Default::allocator(basicAllocator))
397/// , d_value()
398/// {
399/// // ...
400/// }
401///
402/// /// Create a `MyType` object having the specified `value`.
403/// /// Optionally specify a `basicAllocator` used to supply memory. If
404/// /// `basicAllocator` is 0, the currently installed default allocator
405/// /// is used.
406/// explicit MyType(int value,
407/// bslma::Allocator *basicAllocator = 0)
408/// : d_allocator_p(bslma::Default::allocator(basicAllocator))
409/// , d_value(value)
410/// {
411/// // ...
412/// }
413///
414/// /// Create a `MyType` object having the same value as the specified
415/// /// `original` object. Optionally specify a `basicAllocator` used
416/// /// to supply memory. If `basicAllocator` is 0, the currently
417/// /// installed default allocator is used.
418/// MyType(const MyType& original, bslma::Allocator *basicAllocator = 0)
419/// : d_allocator_p(bslma::Default::allocator(basicAllocator))
420/// , d_value(original.value())
421/// {
422/// // ...
423/// }
424///
425/// // ...
426///
427/// // ACCESSORS
428///
429/// /// Return the allocator used by this object to supply memory.
430/// bslma::Allocator *allocator() const
431/// {
432/// return d_allocator_p;
433/// }
434///
435/// /// Return the value of this object.
436/// int value() const
437/// {
438/// return d_value;
439/// }
440///
441/// // ...
442/// };
443/// @endcode
444/// Finally, we instantiate `MyContainer` using `MyType` and verify that, when
445/// we provide an allocator to the constructor of the container, the same
446/// allocator is passed to the constructor of the contained element. Because
447/// the container and the element implement different allocator models, the
448/// invocation of `bslma::ConstructionUtil::construct` automatically adapts the
449/// `bsl::allocator` held by the container to a `bslma::Allocator` pointer
450/// expected by the element. We also verify that, when the container is
451/// copy-constructed without supplying an allocator, the copy uses the default
452/// allocator, not the allocator from the original object. Moreover, we verify
453/// that the element stored in the copy also uses the default allocator:
454/// @code
455/// int main()
456/// {
457/// bslma::TestAllocator testAlloc;
458/// bslma::TestAllocator testAlloc2;
459///
460/// MyContainer<MyType> C1(&testAlloc); // extended default constructor
461/// assert(C1.get_allocator() == &testAlloc);
462/// assert(C1.front().allocator() == &testAlloc);
463/// assert(C1.front().value() == 0);
464///
465/// MyContainer<MyType> C2(MyType(22), &testAlloc); // value constructor
466/// assert(C2.get_allocator() == &testAlloc);
467/// assert(C2.front().allocator() == &testAlloc);
468/// assert(C2.front().value() == 22);
469///
470/// MyContainer<MyType> C3(C2);
471/// assert(C3.get_allocator() != C2.get_allocator());
472/// assert(C3.get_allocator() == bslma::Default::defaultAllocator());
473/// assert(C3.front().allocator() != C1.front().allocator());
474/// assert(C3.front().allocator() == bslma::Default::defaultAllocator());
475/// assert(C3.front().value() == 22);
476///
477/// MyContainer<MyType> C4(C2, &testAlloc2);
478/// assert(C4.get_allocator() == &testAlloc2);
479/// assert(C4.front().allocator() == &testAlloc2);
480/// assert(C4.front().value() == 22);
481/// }
482/// @endcode
483///
484/// ### Example 3: Constructing into Non-heap Memory {#bslma_constructionutil-example-3-constructing-into-non-heap-memory}
485///
486///
487/// This example demonstrates using `bslma::ConstructionUtil::make` to
488/// implement a simple wrapper class that contains a single item that might or
489/// might not use the `bslma` allocator protocol.
490///
491/// First, we define a wrapper class that holds an object and a functor. The
492/// functor (known as the *listener*) is called each time the wrapped object is
493/// changes. We store the object directly as a member variable, instead of
494/// using an uninitialized buffer, to avoid a separate construction step:
495/// @code
496/// /// This class is a wrapper around an object of the specified `TYPE`
497/// /// that triggers a call to an object, called the "listener", of the
498/// /// specified `FUNC` invocable type whenever the wrapped object is
499/// /// changed.
500/// template <class TYPE, class FUNC>
501/// class MyTriggeredWrapper {
502///
503/// // DATA
504/// TYPE d_value;
505/// FUNC d_listener;
506///
507/// public:
508/// typedef bsl::allocator<> allocator_type;
509///
510/// // CREATORS
511///
512/// /// Create an object with the specified `f` as the listener to be
513/// /// called when a change is triggered. Optionally specify `v` as
514/// /// the wrapped value; otherwise the wrapped value is default
515/// /// constructed. Optionally specify `allocator` to supply
516/// /// memory; otherwise the current default allocator is used. If
517/// /// `TYPE` is not allocator aware, `allocator` is ignored.
518/// explicit
519/// MyTriggeredWrapper(const FUNC& f,
520/// const allocator_type& allocator = allocator_type());
521/// MyTriggeredWrapper(const TYPE& v,
522/// const FUNC& f,
523/// const allocator_type& allocator = allocator_type());
524///
525/// /// Create a copy of the specified `original`. Optionally specify
526/// /// `allocator` to supply memory; otherwise the current
527/// /// default allocator is used.
528/// MyTriggeredWrapper(const MyTriggeredWrapper& original,
529/// const allocator_type& allocator = allocator_type());
530///
531/// /// Destroy the wrapped object and listener.
532/// ~MyTriggeredWrapper()
533/// {
534/// }
535///
536/// // MANIPULATORS
537///
538/// /// Assign to the wrapped value the value of the specified `rhs`,
539/// /// invoke the listener with the new value, and return a reference
540/// /// providing modifiable access to this object. Note that the
541/// /// listener itself is not assigned.
542/// MyTriggeredWrapper& operator=(const TYPE& rhs);
543/// MyTriggeredWrapper& operator=(const MyTriggeredWrapper& rhs);
544///
545/// /// Set the wrapped value to the specified `value` and invoke the
546/// /// listener with the new value.
547/// void setValue(const TYPE& value);
548///
549/// // ACCESSORS
550///
551/// /// Return a reference providing read-only access to the wrapped
552/// /// value.
553/// const TYPE& value() const
554/// {
555/// return d_value;
556/// }
557///
558/// /// Return a reference providing read-only access to the listener.
559/// const FUNC& listener() const
560/// {
561/// return d_listener;
562/// }
563/// };
564/// @endcode
565/// Next, we define the constructors such that they initialize `d_value` using
566/// the specified allocator if and only if `TYPE` accepts an allocator. The
567/// `bslma::ConstructionUtil::make` family of functions encapsulate all of the
568/// metaprogramming that detects whether `TYPE` uses an allocator and, if so,
569/// which construction protocol it uses (allocator at the front or at the back
570/// of the argument list), making all three constructors straightforward:
571/// @code
572/// template <class TYPE, class FUNC>
573/// MyTriggeredWrapper<TYPE, FUNC>::MyTriggeredWrapper(
574/// const FUNC& f,
575/// const allocator_type& allocator)
576/// : d_value(bslma::ConstructionUtil::make<TYPE>(allocator))
577/// , d_listener(f)
578/// {
579/// }
580///
581/// template <class TYPE, class FUNC>
582/// MyTriggeredWrapper<TYPE, FUNC>::MyTriggeredWrapper(
583/// const TYPE& v,
584/// const FUNC& f,
585/// const allocator_type& allocator)
586/// : d_value(bslma::ConstructionUtil::make<TYPE>(allocator, v))
587/// , d_listener(f)
588/// {
589/// }
590///
591/// template <class TYPE, class FUNC>
592/// MyTriggeredWrapper<TYPE, FUNC>::MyTriggeredWrapper(
593/// const MyTriggeredWrapper& other,
594/// const allocator_type& allocator)
595/// : d_value(bslma::ConstructionUtil::make<TYPE>(allocator, other.value()))
596/// , d_listener(other.d_listener)
597/// {
598/// }
599/// @endcode
600/// Note that, for `d_value` to be constructed with the correct allocator, the
601/// compiler must construct the result returned from `make` directly into the
602/// `d_value` variable, an optimization known prior to C++17 as "copy elision".
603/// This optimization is required by the C++17 standard and is optional in
604/// pre-2017 standards, but is implemented in all of the C++11 compilers for
605/// which this component is expected to be used at Bloomberg.
606///
607/// Next, we implement the assignment operators, which simply call `setValue`:
608/// @code
609/// template <class TYPE, class FUNC>
610/// MyTriggeredWrapper<TYPE, FUNC>&
611/// MyTriggeredWrapper<TYPE, FUNC>::operator=(const TYPE& rhs)
612/// {
613/// setValue(rhs);
614/// return *this;
615/// }
616///
617/// template <class TYPE, class FUNC>
618/// MyTriggeredWrapper<TYPE, FUNC>&
619/// MyTriggeredWrapper<TYPE, FUNC>::operator=(const MyTriggeredWrapper& rhs)
620/// {
621/// setValue(rhs.value());
622/// return *this;
623/// }
624/// @endcode
625/// Then, we implement `setValue`, which calls the listener after modifying the
626/// value:
627/// @code
628/// template <class TYPE, class FUNC>
629/// void MyTriggeredWrapper<TYPE, FUNC>::setValue(const TYPE& value)
630/// {
631/// d_value = value;
632/// d_listener(d_value);
633/// }
634/// @endcode
635/// Finally, we check our work by creating a listener for `MyContainer<int>`
636/// that stores its last-seen value in a known location and a wrapper around
637/// `MyContainer<int>` to test it:
638/// @code
639/// int lastSeen = 0;
640/// void myListener(const MyContainer<int>& c)
641/// {
642/// lastSeen = c.front();
643/// }
644///
645/// int main()
646/// {
647/// bslma::TestAllocator testAlloc;
648/// MyTriggeredWrapper<MyContainer<int>,
649/// void (*)(const MyContainer<int>&)>
650/// wrappedContainer(myListener, &testAlloc);
651/// assert(&testAlloc == wrappedContainer.value().get_allocator());
652///
653/// wrappedContainer = MyContainer<int>(99);
654///
655/// assert(99 == lastSeen);
656/// }
657/// @endcode
658/// @}
659/** @} */
660/** @} */
661
662/** @addtogroup bsl
663 * @{
664 */
665/** @addtogroup bslma
666 * @{
667 */
668/** @addtogroup bslma_constructionutil
669 * @{
670 */
671
672#include <bslscm_version.h>
673
674#include <bslma_allocator.h>
678
679#include <bslmf_allocatorargt.h>
680#include <bslmf_enableif.h>
683#include <bslmf_isclass.h>
684#include <bslmf_isconvertible.h>
685#include <bslmf_isfundamental.h>
687#include <bslmf_ispointer.h>
688#include <bslmf_movableref.h>
689#include <bslmf_removecv.h>
691#include <bslmf_util.h> // 'forward(V)'
692#include <bslmf_voidtype.h>
693
694#include <bsls_assert.h>
696#include <bsls_libraryfeatures.h>
697#include <bsls_platform.h>
698#include <bsls_util.h> // 'forward<T>(V)'
699
700#include <stddef.h>
701#include <string.h>
702
703#include <new> // placement 'new'
704
705#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
706// Include version that can be compiled with C++03
707// Generated on Tue Oct 4 14:49:46 2022
708// Command line: sim_cpp11_features.pl bslma_constructionutil.h
709# define COMPILING_BSLMA_CONSTRUCTIONUTIL_H
711# undef COMPILING_BSLMA_CONSTRUCTIONUTIL_H
712#else
713
714
715namespace bslma {
716
717// Workaround for optimization issue in xlC that mishandles pointer aliasing.
718// IV56864: ALIASING BEHAVIOUR FOR PLACEMENT NEW
719// http://www-01.ibm.com/support/docview.wss?uid=swg1IV56864
720// Place this macro following each use of placement new. Alternatively,
721// compile with xlC_r -qalias=noansi, which reduces optimization opportunities
722// across entire translation unit instead of simply across optimization fence.
723// Update: issue is fixed in xlC 13.1 (__xlC__ >= 0x0d01).
724
725#if defined(BSLS_PLATFORM_CMP_IBM) && BSLS_PLATFORM_CMP_VERSION < 0x0d01
726 #define BSLMA_CONSTRUCTIONUTIL_XLC_PLACEMENT_NEW_FIX \
727 BSLS_PERFORMANCEHINT_OPTIMIZATION_FENCE
728#else
729 #define BSLMA_CONSTRUCTIONUTIL_XLC_PLACEMENT_NEW_FIX
730#endif
731
732struct ConstructionUtil_Imp;
733
734 // =======================
735 // struct ConstructionUtil
736 // =======================
737
738/// This `struct` provides a namespace for utility functions that construct
739/// elements of (a template parameter) `TARGET_TYPE`.
741
742 private:
743 // PRIVATE TYPES
744
745 /// This `typedef` is a convenient alias for the implementation-specific
746 /// utility class defined in this component.
748
749 public:
750 // CLASS METHODS
751
752 /// Create a default-constructed object of (template parameter)
753 /// `TARGET_TYPE` at the specified `address`. If `allocator` is a
754 /// `bslma`-compatible allocator and `TARGET_TYPE` supports
755 /// `bslma`-style allocation, `allocator` is passed to the default
756 /// extended constructor; otherwise, `allocator` is ignored. If the
757 /// constructor throws, the memory at `address` is left in an
758 /// unspecified state. The behavior is undefined unless `address`
759 /// refers to a block that is of sufficient size and properly aligned
760 /// for objects of `TARGET_TYPE`.
761 template <class TARGET_TYPE, class ALLOCATOR>
762 static void construct(TARGET_TYPE *address, const ALLOCATOR& allocator);
763
764#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=13
765# ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
766 // 'ARG1' lvalue overloaded unneeded in C++11 and hits bug in gcc < 10.2.
767 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
768 static void construct(TARGET_TYPE *address,
769 const ALLOCATOR& allocator,
770 ARG1& argument1,
771 ARGS&&... arguments);
772# endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
773
774 /// Create an object of (template parameter) `TARGET_TYPE` at the
775 /// specified `address`, constructed by forwarding the specified
776 /// `argument1` and the (variable number of) additional specified
777 /// `arguments` to the corresponding constructor of `TARGET_TYPE`. If
778 /// the specified `allocator` is a bslma-compatible allocator and
779 /// `TARGET_TYPE` supports `bslma`-style allocation, the allocator is
780 /// passed to the constructor; otherwise, `allocator` is ignored. If
781 /// the constructor throws, the memory at `address` is left in an
782 /// unspecified state. Note that, in C++03, perfect forwarding is
783 /// limited such that any lvalue reference in the `arguments` parameter
784 /// pack is const-qualified when forwarded to the `TARGET_TYPE`
785 /// constructor; only `argument1` can be forwarded as an unqualified
786 /// lvalue. The behavior is undefined unless `address` refers to a
787 /// block that is of sufficient size and properly aligned for objects of
788 /// `TARGET_TYPE`.
789 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
790 static void construct(TARGET_TYPE *address,
791 const ALLOCATOR& allocator,
792 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
793 ARGS&&... arguments);
794#endif
795
796 /// Create an object of (template parameter) `TARGET_TYPE` at the
797 /// specified `address` by moving from the specified `original` object,
798 /// then destroy `original`. The specified `allocator` is unused
799 /// (except possibly in precondition checks). The constructed object
800 /// will have the same allocator (if any) as `original`. If
801 /// `bslmf::IsBitwiseMoveable<TARGET_TYPE>::value` is `true`, then the
802 /// entire operation is a simple `memcpy` -- no constructors or
803 /// destructors are invoked; otherwise, this method move-constructs an
804 /// object at `address` from the object at `original` then invokes the
805 /// destructor on `original`. If the move constructor throws an
806 /// exception, the memory at `address` is left in an uninitialized state
807 /// and `original` is left in a valid but unspecified state. The
808 /// behavior is undefined if `original` uses an allocator other than
809 /// `allocator` to supply memory. Note that if `original` points to an
810 /// object of a type derived from `TARGET_TYPE` (i.e., a slicing move)
811 /// where `TARGET_TYPE` has a non-`virtual` destructor, then `original`
812 /// will be only partially destroyed.
813 template <class TARGET_TYPE, class ALLOCATOR>
814 static void destructiveMove(TARGET_TYPE *address,
815 const ALLOCATOR& allocator,
816 TARGET_TYPE *original);
817
818#if defined(BSLS_COMPILERFEATURES_GUARANTEED_COPY_ELISION)
819 /// Return, by value, an object of the specified (template parameter)
820 /// `TARGET_TYPE`, having default value. If `allocator` is a
821 /// `bslma`-compatible allocator and `TARGET_TYPE` supports
822 /// `bslma`-style allocation, `allocator` is passed to the extended
823 /// default constructor; otherwise, `allocator` is ignored. Note that
824 /// this method is available only for compilers that reliably implement
825 /// copy/move elision (i.e., RVO) on the returned object. This
826 /// copy/move elision is required starting with C++17 and is widely
827 /// implemented, though optional, prior to C++17.
828 template <class TARGET_TYPE, class ALLOCATOR>
829 static TARGET_TYPE make(const ALLOCATOR& allocator);
830
831#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
832# ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
833 // 'ARG1' lvalue overloaded unneeded in C++11 and hits bug in gcc < 10.2.
834 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
835 static TARGET_TYPE make(const ALLOCATOR& allocator,
836 ARG1& argument1,
837 ARGS&&... arguments);
838# endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
839
840 /// Return, by value, an object of the specified (template parameter)
841 /// `TARGET_TYPE`, constructed by forwarding the specified `argument1`
842 /// and the (variable number of) additional specified `arguments` to the
843 /// corresponding constructor of `TARGET_TYPE`. If the specified
844 /// `allocator` is a bslma-compatible allocator and `TARGET_TYPE`
845 /// supports `bslma`-style allocation, the allocator is passed to the
846 /// constructor; otherwise, `allocator` is ignored. Note that this
847 /// method is available only for compilers that reliably implement
848 /// copy/move elision (i.e., RVO) on the returned object. This
849 /// copy/move elision is required starting with C++17 and is widely
850 /// implemented, though optional, prior to C++17. Note that, in C++03,
851 /// perfect forwarding is limited such that any lvalue reference in the
852 /// `arguments` parameter pack is const-qualified when forwarded to the
853 /// `TARGET_TYPE` constructor; only `argument1` can be forwarded as an
854 /// unqualified lvalue.
855 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
856 static TARGET_TYPE make(const ALLOCATOR& allocator,
857 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
858 ARGS&&... arguments);
859#endif
860#endif // defined(BSLS_COMPILERFEATURES_GUARANTEED_COPY_ELISION)
861};
862
863 // ===========================
864 // struct ConstructionUtil_Imp
865 // ===========================
866
867/// This `struct` provides a namespace for a suite of utility functions that
868/// are used to implement functions in `ConstructionUtil`. In particular,
869/// they provide overloads, resolved at compile-time, for various features
870/// (e.g., passing down the allocator to sub-elements of `pair`-like types)
871/// and optimizations (e.g., bypassing the call to the constructor for
872/// classes with trivial default and copy constructors). These functions
873/// should not be used outside this component.
875
876 // TYPES
877
878 /// These constants are used in the overloads below, when the last argument
879 /// is of type `bsl::integral_constant<int, N> *`, indicating that
880 /// `TARGET_TYPE` has the traits for which the enumerator equal to `N` is
881 /// named.
882 enum {
883
887 e_USES_ALLOCATOR_ARG_T_TRAITS // Implies USES_ALLOCATOR
888 };
889
890 // CLASS METHODS
891
892 /// Construct a default instance of (template parameter) `TARGET_TYPE`
893 /// at the specified `address`, passing to the constructor the specified
894 /// `allocator` using the leading or trailing allocator convention,
895 /// according to the specified `integral_constant` tag, or ignoring
896 /// `allocator` in the `e_NIL_TRAITS` case. If the constructor throws,
897 /// the memory at `address` is left in an unspecified state.
898 template <class TARGET_TYPE, class ALLOCATOR>
899 static void construct(
900 TARGET_TYPE *address,
901 const ALLOCATOR& allocator,
903 template <class TARGET_TYPE, class ALLOCATOR>
904 static void construct(
905 TARGET_TYPE *address,
906 const ALLOCATOR& allocator,
908 template <class TARGET_TYPE, class ALLOCATOR>
909 static void construct(
910 TARGET_TYPE *address,
911 const ALLOCATOR& allocator,
913
914#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
915# ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
916 // 'ARG1' lvalue overloaded unneeded in C++11 and hits bug in gcc < 10.2.
917 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
918 static void construct(
919 TARGET_TYPE *address,
920 const ALLOCATOR& allocator,
922 ARG1& argument1,
923 ARGS&&... arguments);
924 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
925 static void construct(
926 TARGET_TYPE *address,
927 const ALLOCATOR& allocator,
929 ARG1& argument1,
930 ARGS&&... arguments);
931 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
932 static void construct(
933 TARGET_TYPE *address,
934 const ALLOCATOR& allocator,
936 ARG1& argument1,
937 ARGS&&... arguments);
938# endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
939
940 /// Construct an instance of (template parameter) `TARGET_TYPE` at the
941 /// specified `address` forwarding to the constructor the specified
942 /// `argument1` and `arguments` arguments and passing the specified
943 /// `allocator` using the leading or trailing allocator convention,
944 /// according to the specified `integral_constant` tag, or ignoring
945 /// `allocator` in the `e_NIL_TRAITS` case. If the constructor throws,
946 /// the memory at `address` is left in an unspecified state.
947 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
948 static void construct(
949 TARGET_TYPE *address,
950 const ALLOCATOR& allocator,
952 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
953 ARGS&&... arguments);
954 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
955 static void construct(
956 TARGET_TYPE *address,
957 const ALLOCATOR& allocator,
959 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
960 ARGS&&... arguments);
961 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
962 static void construct(
963 TARGET_TYPE *address,
964 const ALLOCATOR& allocator,
966 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
967 ARGS&&... arguments);
968#endif
969
970 /// Move the bitwise movable object of (template parameter)
971 /// `TARGET_TYPE` at the specified `original` address to the specified
972 /// `address`, eliding the call to the move constructor and destructor
973 /// in favor of performing a bitwise copy. The specified `allocator`
974 /// argument is ignored (except possibly for precondition checks). The
975 /// behavior is undefined if `original` uses an allocator other than
976 /// `allocator` to supply memory.
977 template <class TARGET_TYPE, class ALLOCATOR>
978 static void destructiveMove(
979 TARGET_TYPE *address,
980 const ALLOCATOR& allocator,
982 TARGET_TYPE *original);
983
984 /// Create an object of (template parameter) `TARGET_TYPE` at the
985 /// specified `address` by move construction from the specified
986 /// `original` object, then destroy `original`. The specified
987 /// `allocator` is unused (except possibly in precondition checks). The
988 /// constructed object will have the same allocator (if any) as
989 /// `original`. If the move constructor throws an exception, the memory
990 /// at `address` is left in an uninitialized state and `original` is
991 /// left in a valid but unspecified state. The behavior is undefined if
992 /// `original` uses an allocator other than `allocator` to supply
993 /// memory. Note that, if `original` points to an object of a type
994 /// derived from `TARGET_TYPE` (i.e., a slicing move) where
995 /// `TARGET_TYPE` has a non-`virtual` destructor, then `original` will
996 /// be only partially destroyed.
997 template <class TARGET_TYPE, class ALLOCATOR>
998 static void destructiveMove(
999 TARGET_TYPE *address,
1000 const ALLOCATOR& allocator,
1002 TARGET_TYPE *original);
1003
1004#if defined(BSLS_COMPILERFEATURES_GUARANTEED_COPY_ELISION)
1005 /// Return, by value, a default-constructed object of (template
1006 /// parameter) `TARGET_TYPE`, passing the specified `allocator` to the
1007 /// constructor using the leading or trailing allocator convention,
1008 /// according to the specified `integral_constant` tag, or ignoring
1009 /// `allocator` in the `e_NIL_TRAITS` case.
1010 template <class TARGET_TYPE, class ALLOCATOR>
1011 static TARGET_TYPE make(
1012 const ALLOCATOR& allocator,
1014 template <class TARGET_TYPE, class ALLOCATOR>
1015 static TARGET_TYPE make(
1016 const ALLOCATOR& allocator,
1018 template <class TARGET_TYPE, class ALLOCATOR>
1019 static TARGET_TYPE make(
1020 const ALLOCATOR& allocator,
1022
1023#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1024# ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1025 // 'ARG1' lvalue overloaded unneeded in C++11 and hits bug in gcc < 10.2.
1026 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1027 static TARGET_TYPE make(
1028 const ALLOCATOR& allocator,
1030 ARG1& argument1,
1031 ARGS&&... arguments);
1032 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1033 static TARGET_TYPE make(
1034 const ALLOCATOR& allocator,
1036 ARG1& argument1,
1037 ARGS&&... arguments);
1038 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1039 static TARGET_TYPE make(
1040 const ALLOCATOR& allocator,
1042 ARG1& argument1,
1043 ARGS&&... arguments);
1044# endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1045
1046 /// Return, by value, an instance of (template parameter) `TARGET_TYPE`,
1047 /// forwarding to the constructor the specified `argument1` and
1048 /// `arguments` arguments and passing the specified `allocator` using
1049 /// the leading or trailing allocator convention, according to the
1050 /// specified `integral_constant` tag, or ignoring `allocator` in the
1051 /// `e_NIL_TRAITS` case.
1052 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1053 static TARGET_TYPE make(
1054 const ALLOCATOR& allocator,
1056 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
1057 ARGS&&... arguments);
1058 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1059 static TARGET_TYPE make(
1060 const ALLOCATOR& allocator,
1062 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
1063 ARGS&&... arguments);
1064 template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1065 static TARGET_TYPE make(
1066 const ALLOCATOR& allocator,
1068 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
1069 ARGS&&... arguments);
1070
1071#endif
1072#endif // defined(BSLS_COMPILERFEATURES_GUARANTEED_COPY_ELISION)
1073
1074 /// Return the specified `address` cast as a pointer to `void`, even if
1075 /// the (template parameter) `TARGET_TYPE` is cv-qualified.
1076 template <class TARGET_TYPE>
1077 static void *voidify(TARGET_TYPE *address);
1078};
1079
1080// ============================================================================
1081// TEMPLATE IMPLEMENTATIONS
1082// ============================================================================
1083
1084 // -----------------------------------------------
1085 // struct template ConstructionUtil_IsAllocatorPtr
1086 // -----------------------------------------------
1087
1088/// Metafunction that inherits from `true_type` if the `ALLOC` type is a
1089/// pointer to `bslma::Allocator` or a class derived from it and
1090/// `false_type` otherwise.
1091template <class ALLOC>
1092struct ConstructionUtil_IsAllocatorPtr;
1093
1094/// This primary template is instantiated only for non-pointer type `ALLOC`
1095/// and always evaluates false.
1096template <class ALLOC>
1099
1100/// This partial specialization is for pointer type `ALLOC *` and evaulates
1101/// true if and only if `ALLOC` is derived from `bslma::Allocator`.
1102template <class ALLOC>
1106
1107 // ---------------------------------------------------
1108 // struct template ConstructionUtil_ConstructionTraits
1109 // ---------------------------------------------------
1110
1111/// Metafunction yielding one of the following three `value` constants:
1112///
1113///: e_USES_ALLOCATOR_ARG_T_TRAITS `TARGET_TYPE` supports an allocator as
1114///: its second constructor argument, after
1115///: `bsl::allocator_arg`.
1116///:
1117///: e_USES_ALLOCATOR_TRAITS `TARGET_TYPE` supports an allocator as
1118///: its last constructor argument.
1119///:
1120///: e_NIL_TRAITS `TARGET_TYPE` does not support an
1121///: allocator and/or `ALLOCATOR` is `void*`
1122///: `int`, or any other non-allocator
1123///: scalar. The allocator argument to
1124///: `construct` will be ignored.
1125///
1126/// `ALLOCATOR` is compatible with an AA `TARGET_TYPE` if `ALLOCATOR` is
1127/// convertible to the allocator type expected by `TARGET_TYPE`'s
1128/// constructors. There are three special cases of incompatible `ALLOCATOR`
1129/// types:
1130///
1131/// 1. If `TARGET_TYPE` expects an allocator of type `bslma::Allocator *`
1132/// this metafunction yields either `e_USES_ALLOCATOR_ARG_T_TRAITS` or
1133/// `e_USES_ALLOCATOR_TRAITS`, even if `ALLOCATOR` is not compatible with
1134/// `TARGET_TYPE`. The `construct` method will attempt to extract the
1135/// `bslma::Allocator *` from the allocator using its `mechanism`
1136/// accessor. If there is no `mechanism` accessor, compilation will
1137/// fail.
1138/// 2. Otherwise, if `bslma::UsesBslmaAllocator<TARGET_TYPE>::value` is
1139/// `true`, this metafunction yields either
1140/// `e_USES_ALLOCATOR_ARG_T_TRAITS` or `e_USES_ALLOCATOR_TRAITS`, even if
1141/// `ALLOCATOR` is not compatible with `TARGET_TYPE`, resulting in a
1142/// compilation error within `construct`.
1143/// 3. Otherwise, if `ALLOCATOR` is incompatible with `TARGET_TYPE`, then
1144/// `ALLOCATOR` is ignored and this metafunction yields `e_NIL_TRAITS`,
1145/// as though `TARGET_TYPE` were not AA.
1146///
1147/// The first two special cases allow mixing and matching between
1148/// `bsl::allocator` and `bslma::Allocator *` in both directions, but will
1149/// fail for other allocator types. The failure is desirable to prevent
1150/// code accidentally passing an incorrect allocator type.
1151///
1152/// The third special case is inconsistent with the other two so as to allow
1153/// third-party classes that use third-party allocators to be treated as
1154/// non-AA within containers that use BDE allocators.
1155///
1156/// This metafunction also yields a `type` of 'bsl::integral_constant<value,
1157/// int>'.
1158template <class TARGET_TYPE, class ALLOCATOR>
1180
1181
1182 // -------------------------------------------------
1183 // struct template ConstructionUtil_AllocAdaptorUtil
1184 // -------------------------------------------------
1185
1186template <class TYPE,
1187 bool HAS_ALLOC_TYPE = HasAllocatorType<TYPE>::value,
1188 bool IS_BSLMA_AA = UsesBslmaAllocator<TYPE>::value>
1190
1191/// This utility class template provides a static `adapt` method that adapts
1192/// an allocator object to the type expected by `TYPE`. This primary
1193/// template is instantiated only for a non-AA `TYPE`; such types do not
1194/// expect an allocator, so no `adapt` method is defined.
1195template <class TYPE>
1196struct ConstructionUtil_AllocAdaptorUtil<TYPE, false, false> {
1197};
1198
1199/// This utility class template provides a static `adapt` method that adapts
1200/// an allocator object to the type expected by `TYPE`. This partial
1201/// specialization is instantiated for types that expect an allocator of
1202/// type `bslma::Allocator *`.
1203template <class TYPE>
1204struct ConstructionUtil_AllocAdaptorUtil<TYPE, false, true> {
1205
1206 /// Return the `bslma::Allocator` pointer held by the specified `a`
1207 /// object of non-pointer class. Compilation will fail if type `ALLOC`
1208 /// does not provide a `mechanism()` accessor returning a pointer to
1209 /// type convertible to `bslma::Allocator *`.
1210 template <class ALLOC>
1211 static bslma::Allocator *adapt(const ALLOC& a) { return a.mechanism(); }
1212
1213 /// Return the specified `alloc_p` pointer, implicitly converted to
1214 /// `bslma::Allocator *`. Compilation will fail unless `ALLOC` is
1215 /// derived from `bslma::Allocator`.
1216 template <class ALLOC>
1217 static bslma::Allocator *adapt(ALLOC *const &alloc_p) { return alloc_p; }
1218};
1219
1220/// This utility class template provides a static `adapt` method that adapts
1221/// an allocator object to the type expected by `TYPE`. This partial
1222/// specialization is instantiated for types that expect an allocator of
1223/// type `TYPE::allocator_type`.
1224template <class TYPE, bool IS_BSLMA_AA>
1225struct ConstructionUtil_AllocAdaptorUtil<TYPE, true, IS_BSLMA_AA> {
1226
1227 /// Return the specified `a` allocator, implicitly converted to
1228 /// `TYPE::allocator_type`. Compilation will fail if implicit
1229 /// conversion to the return type is invalid.
1230 template <class ALLOC>
1231 static typename TYPE::allocator_type adapt(const ALLOC& a) { return a; }
1232};
1233
1234
1235 // -----------------------
1236 // struct ConstructionUtil
1237 // -----------------------
1238
1239// CLASS METHODS
1240template <class TARGET_TYPE, class ALLOCATOR>
1241inline
1242void
1243ConstructionUtil::construct(TARGET_TYPE *address,
1244 const ALLOCATOR& allocator)
1245{
1246 typedef typename
1248
1249 Imp::construct(address, allocator, Trait());
1250}
1251
1252#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1253# ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1254template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1255inline
1256void
1257ConstructionUtil::construct(TARGET_TYPE *address,
1258 const ALLOCATOR& allocator,
1259 ARG1& argument1,
1260 ARGS&&... arguments)
1261{
1262 typedef typename
1264
1265 Imp::construct(address,
1266 allocator,
1267 Trait(),
1268 argument1,
1269 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1270}
1271# endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1272
1273template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1274inline
1275void
1276ConstructionUtil::construct(TARGET_TYPE *address,
1277 const ALLOCATOR& allocator,
1278 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
1279 ARGS&&... arguments)
1280{
1281 typedef typename
1283
1284 Imp::construct(address,
1285 allocator,
1286 Trait(),
1287 BSLS_COMPILERFEATURES_FORWARD(ARG1, argument1),
1288 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1289}
1290#endif
1291
1292template <class TARGET_TYPE, class ALLOCATOR>
1293inline
1294void
1296 const ALLOCATOR& allocator,
1297 TARGET_TYPE *original)
1298{
1299 BSLS_ASSERT_SAFE(address);
1300 BSLS_ASSERT_SAFE(original);
1301
1302 enum {
1306 };
1307
1308 Imp::destructiveMove(address,
1309 allocator,
1311 original);
1312}
1313
1314#if defined(BSLS_COMPILERFEATURES_GUARANTEED_COPY_ELISION)
1315// Suppress bde_verify warnings about return-by-value in this region.
1316// BDE_VERIFY pragma: push
1317// BDE_VERIFY pragma: -AR01: Type using allocator is returned by value
1318
1319template <class TARGET_TYPE, class ALLOCATOR>
1320inline
1321TARGET_TYPE
1322ConstructionUtil::make(const ALLOCATOR& allocator)
1323{
1324 typedef typename
1326
1327 return Imp::make<TARGET_TYPE>(allocator, Trait());
1328}
1329
1330#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1331# ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1332template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1333inline
1334TARGET_TYPE
1335ConstructionUtil::make(const ALLOCATOR& allocator,
1336 ARG1& argument1,
1337 ARGS&&... arguments)
1338{
1339 typedef typename
1341
1342 return Imp::make<TARGET_TYPE>(
1343 allocator,
1344 Trait(),
1345 argument1,
1346 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1347}
1348# endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1349
1350template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1351inline
1352TARGET_TYPE
1353ConstructionUtil::make(const ALLOCATOR& allocator,
1354 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
1355 ARGS&&... arguments)
1356{
1357 typedef typename
1359
1360 return Imp::make<TARGET_TYPE>(
1361 allocator,
1362 Trait(),
1363 BSLS_COMPILERFEATURES_FORWARD(ARG1, argument1),
1364 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1365}
1366#endif
1367
1368// BDE_VERIFY pragma: pop
1369#endif // defined(BSLS_COMPILERFEATURES_GUARANTEED_COPY_ELISION)
1370
1371 // ---------------------------
1372 // struct ConstructionUtil_Imp
1373 // ---------------------------
1374
1375// CLASS METHODS
1376template <class TARGET_TYPE, class ALLOCATOR>
1377inline
1378void
1380 TARGET_TYPE *address,
1381 const ALLOCATOR& allocator,
1383{
1385 ::new (voidify(address)) TARGET_TYPE(bsl::allocator_arg,
1386 AllocUtil::adapt(allocator));
1388}
1389
1390template <class TARGET_TYPE, class ALLOCATOR>
1391inline
1392void
1394 TARGET_TYPE *address,
1395 const ALLOCATOR& allocator,
1397{
1399 ::new (voidify(address)) TARGET_TYPE(AllocUtil::adapt(allocator));
1401}
1402
1403template <class TARGET_TYPE, class ALLOCATOR>
1404inline
1405void
1407 TARGET_TYPE *address,
1408 const ALLOCATOR& ,
1410{
1411 ::new (voidify(address)) TARGET_TYPE();
1413}
1414
1415#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1416# ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1417template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1418inline
1419void
1421 TARGET_TYPE *address,
1422 const ALLOCATOR& allocator,
1424 ARG1& argument1,
1425 ARGS&&... arguments)
1426{
1428 ::new (voidify(address)) TARGET_TYPE(
1429 bsl::allocator_arg,
1430 AllocUtil::adapt(allocator),
1431 argument1,
1432 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1434}
1435
1436template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1437inline
1438void
1440 TARGET_TYPE *address,
1441 const ALLOCATOR& allocator,
1443 ARG1& argument1,
1444 ARGS&&... arguments)
1445{
1447 ::new (voidify(address)) TARGET_TYPE(
1448 argument1,
1449 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...,
1450 AllocUtil::adapt(allocator));
1452}
1453
1454template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1455inline
1456void
1458 TARGET_TYPE *address,
1459 const ALLOCATOR& ,
1461 ARG1& argument1,
1462 ARGS&&... arguments)
1463{
1464 ::new (voidify(address)) TARGET_TYPE(
1465 argument1,
1466 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1468}
1469# endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1470
1471template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1472inline
1473void
1475 TARGET_TYPE *address,
1476 const ALLOCATOR& allocator,
1478 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
1479 ARGS&&... arguments)
1480{
1482 ::new (voidify(address)) TARGET_TYPE(
1483 bsl::allocator_arg,
1484 AllocUtil::adapt(allocator),
1485 BSLS_COMPILERFEATURES_FORWARD(ARG1, argument1),
1486 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1488}
1489
1490template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1491inline
1492void
1494 TARGET_TYPE *address,
1495 const ALLOCATOR& allocator,
1497 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
1498 ARGS&&... arguments)
1499{
1501 ::new (voidify(address)) TARGET_TYPE(
1502 BSLS_COMPILERFEATURES_FORWARD(ARG1, argument1),
1503 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...,
1504 AllocUtil::adapt(allocator));
1506}
1507
1508template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1509inline
1510void
1512 TARGET_TYPE *address,
1513 const ALLOCATOR& ,
1515 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
1516 ARGS&&... arguments)
1517{
1518 ::new (voidify(address)) TARGET_TYPE(
1519 BSLS_COMPILERFEATURES_FORWARD(ARG1, argument1),
1520 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1522}
1523#endif
1524
1525template <class TARGET_TYPE, class ALLOCATOR>
1526inline
1527void
1529 TARGET_TYPE *address,
1530 const ALLOCATOR& ,
1532 TARGET_TYPE *original)
1533{
1536 ::new (voidify(address)) TARGET_TYPE(*original);
1538 }
1539 else {
1540 // voidify(address) is used here to suppress compiler warning
1541 // "-Wclass-memaccess".
1542 memcpy(voidify(address), original, sizeof *original);
1543 }
1544}
1545
1546template <class TARGET_TYPE, class ALLOCATOR>
1547inline
1548void
1550 TARGET_TYPE *address,
1551 const ALLOCATOR& allocator,
1553 TARGET_TYPE *original)
1554{
1555 // TBD: Eventually, we can add a precondition that 'allocator' matches
1556 // 'original''s allocator, but that is not universally detectable right
1557 // now, as not all allocator-aware types provide an 'allocator()' method.
1558 //..
1559 // BSLS_ASSERT(allocator == original->allocator());
1560
1562 allocator,
1563 bslmf::MovableRefUtil::move(*original));
1564 DestructionUtil::destroy(original);
1565}
1566
1567#if defined(BSLS_COMPILERFEATURES_GUARANTEED_COPY_ELISION)
1568// Suppress bde_verify warnings about return-by-value in this region.
1569// BDE_VERIFY pragma: push
1570// BDE_VERIFY pragma: -AR01: Type using allocator is returned by value
1571
1572template <class TARGET_TYPE, class ALLOCATOR>
1573inline
1574TARGET_TYPE
1575ConstructionUtil_Imp::make(
1576 const ALLOCATOR& allocator,
1578{
1580 return TARGET_TYPE(bsl::allocator_arg, AllocUtil::adapt(allocator));
1581}
1582
1583template <class TARGET_TYPE, class ALLOCATOR>
1584inline
1585TARGET_TYPE
1586ConstructionUtil_Imp::make(
1587 const ALLOCATOR& allocator,
1589{
1590 typedef ConstructionUtil_AllocAdaptorUtil<TARGET_TYPE> AllocUtil;
1591 return TARGET_TYPE(AllocUtil::adapt(allocator));
1592}
1593
1594template <class TARGET_TYPE, class ALLOCATOR>
1595inline
1596TARGET_TYPE
1597ConstructionUtil_Imp::make(
1598 const ALLOCATOR& ,
1600{
1601 return TARGET_TYPE();
1602}
1603
1604#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1605# ifndef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1606template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1607inline
1608TARGET_TYPE
1609ConstructionUtil_Imp::make(
1610 const ALLOCATOR& allocator,
1612 ARG1& argument1,
1613 ARGS&&... arguments)
1614{
1615 typedef ConstructionUtil_AllocAdaptorUtil<TARGET_TYPE> AllocUtil;
1616 return TARGET_TYPE(
1617 bsl::allocator_arg,
1618 AllocUtil::adapt(allocator),
1619 argument1,
1620 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1621}
1622
1623template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1624inline
1625TARGET_TYPE
1626ConstructionUtil_Imp::make(
1627 const ALLOCATOR& allocator,
1629 ARG1& argument1,
1630 ARGS&&... arguments)
1631{
1632 typedef ConstructionUtil_AllocAdaptorUtil<TARGET_TYPE> AllocUtil;
1633 return TARGET_TYPE(
1634 argument1,
1635 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...,
1636 AllocUtil::adapt(allocator));
1637}
1638
1639template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1640inline
1641TARGET_TYPE
1642ConstructionUtil_Imp::make(
1643 const ALLOCATOR& ,
1645 ARG1& argument1,
1646 ARGS&&... arguments)
1647{
1648 return TARGET_TYPE(
1649 argument1,
1650 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1651}
1652# endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
1653
1654template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1655inline
1656TARGET_TYPE
1657ConstructionUtil_Imp::make(
1658 const ALLOCATOR& allocator,
1660 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
1661 ARGS&&... arguments)
1662{
1663 typedef ConstructionUtil_AllocAdaptorUtil<TARGET_TYPE> AllocUtil;
1664 return TARGET_TYPE(
1665 bsl::allocator_arg,
1666 AllocUtil::adapt(allocator),
1667 BSLS_COMPILERFEATURES_FORWARD(ARG1, argument1),
1668 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1669}
1670
1671template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1672inline
1673TARGET_TYPE
1674ConstructionUtil_Imp::make(
1675 const ALLOCATOR& allocator,
1677 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
1678 ARGS&&... arguments)
1679{
1680 typedef ConstructionUtil_AllocAdaptorUtil<TARGET_TYPE> AllocUtil;
1681 return TARGET_TYPE(
1682 BSLS_COMPILERFEATURES_FORWARD(ARG1, argument1),
1683 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...,
1684 AllocUtil::adapt(allocator));
1685}
1686
1687template <class TARGET_TYPE, class ALLOCATOR, class ARG1, class... ARGS>
1688inline
1689TARGET_TYPE
1690ConstructionUtil_Imp::make(
1691 const ALLOCATOR& ,
1693 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
1694 ARGS&&... arguments)
1695{
1696 return TARGET_TYPE(
1697 BSLS_COMPILERFEATURES_FORWARD(ARG1, argument1),
1698 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1699}
1700#endif
1701
1702// BDE_VERIFY pragma: pop
1703#endif // defined(BSLS_COMPILERFEATURES_GUARANTEED_COPY_ELISION)
1704
1705template <class TARGET_TYPE>
1706inline
1707void *ConstructionUtil_Imp::voidify(TARGET_TYPE *address)
1708{
1709 return static_cast<void *>(
1710 const_cast<typename bsl::remove_cv<TARGET_TYPE>::type *>(address));
1711}
1712
1713} // close package namespace
1714
1715
1716#endif // End C++11 code
1717
1718#endif
1719
1720// ----------------------------------------------------------------------------
1721// Copyright 2013 Bloomberg Finance L.P.
1722//
1723// Licensed under the Apache License, Version 2.0 (the "License");
1724// you may not use this file except in compliance with the License.
1725// You may obtain a copy of the License at
1726//
1727// http://www.apache.org/licenses/LICENSE-2.0
1728//
1729// Unless required by applicable law or agreed to in writing, software
1730// distributed under the License is distributed on an "AS IS" BASIS,
1731// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1732// See the License for the specific language governing permissions and
1733// limitations under the License.
1734// ----------------------------- END-OF-FILE ----------------------------------
1735
1736/** @} */
1737/** @} */
1738/** @} */
#define BSLMA_CONSTRUCTIONUTIL_XLC_PLACEMENT_NEW_FIX
Definition bslma_constructionutil.h:729
Definition bslma_allocator.h:457
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2012
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2018
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balxml_encoderoptions.h:68
Definition bslmf_integralconstant.h:244
Definition bslmf_isclass.h:163
Definition bslmf_isconvertible.h:867
Definition bslmf_isfundamental.h:329
Definition bslmf_ispointer.h:138
remove_const< typenameremove_volatile< t_TYPE >::type >::type type
Definition bslmf_removecv.h:126
Definition bslmf_usesallocator.h:165
static bslma::Allocator * adapt(const ALLOC &a)
Definition bslma_constructionutil.h:1211
static bslma::Allocator * adapt(ALLOC *const &alloc_p)
Definition bslma_constructionutil.h:1217
static TYPE::allocator_type adapt(const ALLOC &a)
Definition bslma_constructionutil.h:1231
Definition bslma_constructionutil.h:1189
Definition bslma_constructionutil.h:1159
bsl::integral_constant< int, value > type
Definition bslma_constructionutil.h:1178
@ value
Definition bslma_constructionutil.h:1168
Definition bslma_constructionutil.h:874
static void destructiveMove(TARGET_TYPE *address, const ALLOCATOR &allocator, bsl::integral_constant< int, e_BITWISE_MOVABLE_TRAITS >, TARGET_TYPE *original)
Definition bslma_constructionutil.h:1528
static void * voidify(TARGET_TYPE *address)
Definition bslma_constructionutil.h:1707
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator, bsl::integral_constant< int, e_USES_ALLOCATOR_ARG_T_TRAITS >)
Definition bslma_constructionutil.h:1379
@ e_NIL_TRAITS
Definition bslma_constructionutil.h:884
@ e_BITWISE_MOVABLE_TRAITS
Definition bslma_constructionutil.h:885
@ e_USES_ALLOCATOR_ARG_T_TRAITS
Definition bslma_constructionutil.h:887
@ e_USES_ALLOCATOR_TRAITS
Definition bslma_constructionutil.h:886
Definition bslma_constructionutil.h:1097
Definition bslma_constructionutil.h:740
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator)
Definition bslma_constructionutil.h:1243
static void destructiveMove(TARGET_TYPE *address, const ALLOCATOR &allocator, TARGET_TYPE *original)
Definition bslma_constructionutil.h:1295
Definition bslma_hasallocatortype.h:175
Definition bslma_usesbslmaallocator.h:343
Definition bslmf_isbitwisemoveable.h:718
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1060
Definition bslmf_usesallocatorargt.h:100