BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslma_allocatortraits.h
Go to the documentation of this file.
1/// @file bslma_allocatortraits.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_allocatortraits.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_ALLOCATORTRAITS
9#define INCLUDED_BSLMA_ALLOCATORTRAITS
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_allocatortraits bslma_allocatortraits
15/// @brief Provide a uniform interface to standard allocator types.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_allocatortraits
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_allocatortraits-purpose"> Purpose</a>
25/// * <a href="#bslma_allocatortraits-classes"> Classes </a>
26/// * <a href="#bslma_allocatortraits-description"> Description </a>
27/// * <a href="#bslma_allocatortraits-usage"> Usage </a>
28/// * <a href="#bslma_allocatortraits-example-1-a-container-class"> Example 1: A Container Class </a>
29/// * <a href="#bslma_allocatortraits-example-2-c-03-allocators"> Example 2: C++03 Allocators </a>
30///
31/// # Purpose {#bslma_allocatortraits-purpose}
32/// Provide a uniform interface to standard allocator types.
33///
34/// # Classes {#bslma_allocatortraits-classes}
35///
36/// - bsl::allocator_traits: Uniform interface to standard allocator types
37///
38/// @see bslma_allocator, bslma_bslallocator
39///
40/// TBD: update component-level doc
41/// # Description {#bslma_allocatortraits-description}
42/// The standard `allocator_traits` class template is defined in
43/// the C++11 standard ([allocator.traits]) as a uniform mechanism for accessing
44/// nested types within, and operations on, any standard-conforming allocator.
45/// An `allocator_traits` specialization is stateless, and all of its member
46/// functions are static. In most cases, facilities of `allocator_traits` are
47/// straight pass-throughs for the same facilities from the `ALLOC` template
48/// parameter. For example, `allocator_traits<X>::pointer` is the same as
49/// `X::pointer` and `allocator_traits<X>::allocate(x, n)` is the same as
50/// `x.allocate(n)`. The advantage of using `allocator_traits` instead of
51/// directly using the allocator is that the `allocator_traits` interface can
52/// supply parts of the interface that are missing from `ALLOC`. In fact, the
53/// most important purpose of `allocator_traits` is to provide implementations
54/// of C++11 allocator features that were absent in C++03, thus allowing a C++03
55/// allocator to work with C++11 containers.
56///
57/// This component provides a full C++11 interface for `allocator_traits`, but
58/// constrains the set of allocator types on which it may be instantiated.
59/// Specifically, this implementation does not provide defaults for C++03 types
60/// and functions, and has hard-wired implementations of the new C++11 features.
61/// Thus, the `allocator_traits` template cannot be instantiated on an allocator
62/// type that does not provide a full compliment of types and functions required
63/// by the C++03 standard, and it will ignore any special C++11 features
64/// specified in `ALLOC`. This limitation exists because Bloomberg does not
65/// need the full functionality of the C++11 model, but needs only to
66/// distinguish between C++03 allocators and allocators that implement the BSLMA
67/// allocator model (see @ref bslma_bslallocator ). The full feature set of
68/// `allocator_traits` would require a lot of resources for implementation and
69/// (especially) testing. Moreover, a full implementation would require
70/// metaprogramming that is too advanced for the feature set of the compilers
71/// currently in use at Bloomberg. This interface is useful, however, as a way
72/// to future-proof containers against the eventual implementation of the full
73/// feature set, and to take advantage of the Bloomberg-specific features
74/// described below.
75///
76/// There are two important (new) C++11 features provided by the
77/// `allocator_traits` interface: the `construct` function having a
78/// variable-length argument list (limited to 5 constructor arguments on
79/// compilers that don't support variadic templates) and the
80/// allocator-propagation traits. The implementations of these features within
81/// this component are tuned to Bloomberg's needs. The `construct` member
82/// function will automatically forward the allocator to the constructed object
83/// iff the `ALLOC` parameter is convertible from `bslma::Allocator*` and the
84/// object being constructed has the `bslma::UsesBslmaAllocator` type trait, as
85/// per standard Bloomberg practice. The
86/// @ref select_on_container_copy_construction static member will return a
87/// default-constructed allocator iff `ALLOC` is convertible from
88/// `bslma::Allocator *` because bslma allocators should not be copied when a
89/// container is copy-constructed; otherwise this function will return a copy of
90/// the allocator, as per C++03 container rules. The other propagation traits
91/// all have a `false` value, so allocators are not propagated on assignment or
92/// swap.
93///
94/// Note that use of this component will differ from a strict following of the
95/// C++03 standard, as the `construct` and `destroy` methods of the
96/// parameterized allocator type will not be called. Rather, the target object
97/// will always be constructed at the address specified by the user, by calling
98/// the constructor in-place. Similarly, the destructor will always be called
99/// directly, rather than using a parameterized allocator's `destroy` method.
100/// Otherwise, this implementation will fully support the C++03 model, including
101/// use of allocators returning "smart pointers" from `allocate`.
102///
103/// ## Usage {#bslma_allocatortraits-usage}
104///
105///
106/// In this section we show intended usage of this component.
107///
108/// ### Example 1: A Container Class {#bslma_allocatortraits-example-1-a-container-class}
109///
110///
111/// This example demonstrates the intended use of `allocator_traits` to
112/// implement a standard-conforming container class. First, we create a
113/// container class that holds a single object and which meets the requirements
114/// both of a standard container and of a Bloomberg container. I.e., when
115/// instantiated with an allocator argument it uses the standard allocator
116/// model; otherwise it uses the `bslma` model. We provide an alias,
117/// `AllocTraits`, to the specific `allocator_traits` instantiation to simplify
118/// the implementation of each method that must allocate memory, or create or
119/// destroy elements.
120/// @code
121/// #include <bslma_allocatortraits.h>
122///
123/// using namespace BloombergLP;
124///
125/// /// This class provides a container that always holds exactly one
126/// /// element, dynamically allocated using the specified allocator.
127/// template <class TYPE, class ALLOC = bsl::allocator<TYPE> >
128/// class MyContainer {
129///
130/// /// Alias for the `allocator_traits` instantiation to use for all
131/// /// memory management requests.
132/// typedef bsl::allocator_traits<ALLOC> AllocTraits;
133///
134/// // DATA
135/// ALLOC d_allocator;
136/// TYPE *d_value_p;
137///
138/// public:
139/// typedef TYPE value_type;
140/// typedef ALLOC allocator_type;
141/// // etc.
142///
143/// // CREATORS
144/// explicit MyContainer(const ALLOC& a = ALLOC());
145/// explicit MyContainer(const TYPE& v, const ALLOC& a = ALLOC());
146/// MyContainer(const MyContainer& other);
147/// MyContainer(const MyContainer& other, const ALLOC& a);
148/// ~MyContainer();
149///
150/// // MANIPULATORS
151/// ALLOC get_allocator() const { return d_allocator; }
152///
153/// // ACCESSORS
154/// TYPE& front() { return *d_value_p; }
155/// const TYPE& front() const { return *d_value_p; }
156///
157/// // etc.
158/// @endcode
159/// Next we define the type traits for `MyContainer` so that it is recognized as
160/// an STL *sequence* container:
161/// * Defines STL iterators
162/// * Is bitwise moveable if the allocator is bitwise moveable
163/// * Uses `bslma` allocators if the `ALLOC` template parameter is convertible
164/// from `bslma::Allocator*`.
165/// @code
166/// // TRAITS
167///
168/// // We would do the following if 'bslalg' was accessible.
169/// // BSLMF_NESTED_TRAIT_DECLARATION(
170/// // MyContainer, bslalg::HasStlIterators);
171///
172/// BSLMF_NESTED_TRAIT_DECLARATION_IF(
173/// MyContainer,
174/// bslmf::IsBitwiseMoveable,
175/// bslmf::IsBitwiseMoveable<ALLOC>::value);
176///
177/// BSLMF_NESTED_TRAIT_DECLARATION_IF(
178/// MyContainer,
179/// bslma::UsesBslmaAllocator,
180/// (bsl::is_convertible<bslma::Allocator*, ALLOC>::value));
181/// };
182/// @endcode
183/// Then we implement the constructors, which allocate memory and construct a
184/// `TYPE` object in the allocated memory. Because the allocation and
185/// construction are done in two separate steps, we need to create a proctor
186/// that will deallocate the allocated memory in case the constructor throws an
187/// exception. The proctor uses the uniform interface provided by
188/// `allocator_traits` to access the `pointer` and `deallocate` members of
189/// `ALLOC`:
190/// @code
191/// /// This class implements a proctor to release memory allocated during
192/// /// the construction of a `MyContainer` object if the constructor for
193/// /// the container's data element throws an exception. Such a proctor
194/// /// should be `release`d once the element is safely constructed.
195/// template <class ALLOC>
196/// class MyContainerProctor {
197///
198/// typedef typename bsl::allocator_traits<ALLOC>::pointer pointer;
199/// ALLOC d_alloc;
200/// pointer d_data_p;
201///
202/// public:
203/// MyContainerProctor(const ALLOC& a, pointer p)
204/// : d_alloc(a), d_data_p(p) { }
205///
206/// ~MyContainerProctor() {
207/// if (d_data_p) {
208/// bsl::allocator_traits<ALLOC>::deallocate(d_alloc, d_data_p, 1);
209/// }
210/// }
211///
212/// void release() { d_data_p = pointer(); }
213/// };
214/// @endcode
215/// Next, we perform the actual allocation and construction using the `allocate`
216/// and `construct` members of `allocator_traits`, which provide the correct
217/// semantic for passing the allocator to the constructed object when
218/// appropriate:
219/// @code
220/// template <class TYPE, class ALLOC>
221/// MyContainer<TYPE, ALLOC>::MyContainer(const ALLOC& a)
222/// : d_allocator(a)
223/// {
224/// d_value_p = AllocTraits::allocate(d_allocator, 1);
225/// MyContainerProctor<ALLOC> proctor(a, d_value_p);
226/// // Call 'construct' with no constructor arguments
227/// AllocTraits::construct(d_allocator, d_value_p);
228/// proctor.release();
229/// }
230///
231/// template <class TYPE, class ALLOC>
232/// MyContainer<TYPE, ALLOC>::MyContainer(const TYPE& v, const ALLOC& a)
233/// : d_allocator(a)
234/// {
235/// d_value_p = AllocTraits::allocate(d_allocator, 1);
236/// MyContainerProctor<ALLOC> proctor(a, d_value_p);
237/// // Call 'construct' with one constructor argument of type 'TYPE'
238/// AllocTraits::construct(d_allocator, d_value_p, v);
239/// proctor.release();
240/// }
241/// @endcode
242/// Next, the copy constructor for `MyContainer` needs to conditionally copy the
243/// allocator from the `other` container. The copy constructor uses
244/// `allocator_traits::select_on_container_copy_construction` to decide whether
245/// to copy the `other` allocator (for non-bslma allocators) or to
246/// default-construct the allocator (for bslma allocators).
247/// @code
248/// template <class TYPE, class ALLOC>
249/// MyContainer<TYPE, ALLOC>::MyContainer(const MyContainer& other)
250/// : d_allocator(bsl::allocator_traits<ALLOC>::
251/// select_on_container_copy_construction(other.d_allocator))
252/// {
253/// d_value_p = AllocTraits::allocate(d_allocator, 1);
254/// MyContainerProctor<ALLOC> proctor(d_allocator, d_value_p);
255/// AllocTraits::construct(d_allocator, d_value_p, *other.d_value_p);
256/// proctor.release();
257/// }
258/// @endcode
259/// Now, the destructor uses `allocator_traits` functions to destroy and
260/// deallocate the value object:
261/// @code
262/// template <class TYPE, class ALLOC>
263/// MyContainer<TYPE, ALLOC>::~MyContainer()
264/// {
265/// AllocTraits::destroy(d_allocator, d_value_p);
266/// AllocTraits::deallocate(d_allocator, d_value_p, 1);
267/// }
268/// @endcode
269/// Finally, we perform a simple test of `MyContainer`, instantiating it with
270/// element type `int`:
271/// @code
272/// int usageExample1()
273/// {
274/// bslma::TestAllocator testAlloc;
275/// MyContainer<int> C1(123, &testAlloc);
276/// assert(C1.get_allocator() == bsl::allocator<int>(&testAlloc));
277/// assert(C1.front() == 123);
278///
279/// MyContainer<int> C2(C1);
280/// assert(C2.get_allocator() == bsl::allocator<int>());
281/// assert(C2.front() == 123);
282///
283/// return 0;
284/// }
285/// @endcode
286/// ### Example 2: C++03 Allocators {#bslma_allocatortraits-example-2-c-03-allocators}
287///
288///
289/// This example shows that when `MyContainer` is instantiated with a C++03
290/// allocator, that the allocator is a) copied on copy construction and b) is
291/// not propagated from the container to its elements. Firstly we create a
292/// representative element class, `MyType`, that allocates memory using the
293/// bslma allocator protocol:
294/// @code
295/// #include <bslma_default.h>
296///
297/// class MyType {
298///
299/// bslma::Allocator *d_allocator_p;
300/// // etc.
301/// public:
302/// // TRAITS
303/// BSLMF_NESTED_TRAIT_DECLARATION(MyType, bslma::UsesBslmaAllocator);
304///
305/// // CREATORS
306/// explicit MyType(bslma::Allocator* basicAlloc = 0)
307/// : d_allocator_p(bslma::Default::allocator(basicAlloc)) { /* ... */ }
308/// MyType(const MyType&)
309/// : d_allocator_p(bslma::Default::allocator(0)) { /* ... */ }
310/// MyType(const MyType&, bslma::Allocator* basicAlloc)
311/// : d_allocator_p(bslma::Default::allocator(basicAlloc)) { /* ... */ }
312/// // etc.
313///
314/// // ACCESSORS
315/// bslma::Allocator *allocator() const { return d_allocator_p; }
316///
317/// // etc.
318/// };
319/// @endcode
320/// Then we create a C++03-style allocator class template:
321/// @code
322/// template <class TYPE>
323/// class MyCpp03Allocator {
324/// int d_state;
325///
326/// public:
327/// typedef TYPE value_type;
328/// typedef TYPE *pointer;
329/// typedef const TYPE *const_pointer;
330/// typedef unsigned size_type;
331/// typedef int difference_type;
332///
333/// template <class OTHER>
334/// struct rebind {
335/// typedef MyCpp03Allocator<OTHER> other;
336/// };
337///
338/// // CREATORS
339/// explicit MyCpp03Allocator(int state = 0) : d_state(state) { }
340///
341/// // ALLOCATION FUNCTIONS
342/// TYPE* allocate(size_type n, const void* = 0)
343/// { return static_cast<TYPE *>(::operator new(sizeof(TYPE) * n)); }
344///
345/// void deallocate(TYPE* p, size_type) { ::operator delete(p); }
346///
347/// // ELEMENT CREATION FUNCTIONS
348/// template <class ELEMENT_TYPE>
349/// void construct(ELEMENT_TYPE *p)
350/// {
351/// ::new (static_cast<void *>(p)) ELEMENT_TYPE();
352/// }
353/// template <class ELEMENT_TYPE, class A1>
354/// void construct(ELEMENT_TYPE *p,
355/// BSLS_COMPILERFEATURES_FORWARD_REF(A1) a1)
356/// {
357/// ::new (static_cast<void *>(p))
358/// ELEMENT_TYPE(BSLS_COMPILERFEATURES_FORWARD(A1, a1));
359/// }
360/// template <class ELEMENT_TYPE, class A1, class A2>
361/// void construct(ELEMENT_TYPE *p,
362/// BSLS_COMPILERFEATURES_FORWARD_REF(A1) a1,
363/// BSLS_COMPILERFEATURES_FORWARD_REF(A2) a2)
364/// {
365/// ::new (static_cast<void *>(p))
366/// ELEMENT_TYPE(BSLS_COMPILERFEATURES_FORWARD(A1, a1),
367/// BSLS_COMPILERFEATURES_FORWARD(A2, a2));
368/// }
369///
370/// template <class ELEMENT_TYPE, class A1, class A2, class A3>
371/// void construct(ELEMENT_TYPE *p,
372/// BSLS_COMPILERFEATURES_FORWARD_REF(A1) a1,
373/// BSLS_COMPILERFEATURES_FORWARD_REF(A2) a2,
374/// BSLS_COMPILERFEATURES_FORWARD_REF(A3) a3)
375/// {
376/// ::new (static_cast<void *>(p))
377/// ELEMENT_TYPE(BSLS_COMPILERFEATURES_FORWARD(A1, a1),
378/// BSLS_COMPILERFEATURES_FORWARD(A2, a2),
379/// BSLS_COMPILERFEATURES_FORWARD(A3, a3));
380/// }
381///
382/// template <class ELEMENT_TYPE, class A1, class A2, class A3, class A4>
383/// void construct(ELEMENT_TYPE *p,
384/// BSLS_COMPILERFEATURES_FORWARD_REF(A1) a1,
385/// BSLS_COMPILERFEATURES_FORWARD_REF(A2) a2,
386/// BSLS_COMPILERFEATURES_FORWARD_REF(A3) a3,
387/// BSLS_COMPILERFEATURES_FORWARD_REF(A4) a4)
388/// {
389/// ::new (static_cast<void *>(p))
390/// ELEMENT_TYPE(BSLS_COMPILERFEATURES_FORWARD(A1, a1),
391/// BSLS_COMPILERFEATURES_FORWARD(A2, a2),
392/// BSLS_COMPILERFEATURES_FORWARD(A3, a3),
393/// BSLS_COMPILERFEATURES_FORWARD(A4, a4));
394/// }
395///
396/// template <class ELEMENT_TYPE,
397/// class A1,
398/// class A2,
399/// class A3,
400/// class A4,
401/// class A5>
402/// void construct(ELEMENT_TYPE *p,
403/// BSLS_COMPILERFEATURES_FORWARD_REF(A1) a1,
404/// BSLS_COMPILERFEATURES_FORWARD_REF(A2) a2,
405/// BSLS_COMPILERFEATURES_FORWARD_REF(A3) a3,
406/// BSLS_COMPILERFEATURES_FORWARD_REF(A4) a4,
407/// BSLS_COMPILERFEATURES_FORWARD_REF(A5) a5)
408/// {
409/// ::new (static_cast<void *>(p))
410/// ELEMENT_TYPE(BSLS_COMPILERFEATURES_FORWARD(A1, a1),
411/// BSLS_COMPILERFEATURES_FORWARD(A2, a2),
412/// BSLS_COMPILERFEATURES_FORWARD(A3, a3),
413/// BSLS_COMPILERFEATURES_FORWARD(A4, a4),
414/// BSLS_COMPILERFEATURES_FORWARD(A5, a5));
415/// }
416///
417/// template <class ELEMENT_TYPE>
418/// void destroy(ELEMENT_TYPE *p) { p->~ELEMENT_TYPE(); }
419///
420/// // ACCESSORS
421/// static size_type max_size() { return UINT_MAX / sizeof(TYPE); }
422///
423/// int state() const { return d_state; }
424/// };
425///
426/// template <class TYPE1, class TYPE2>
427/// inline
428/// bool operator==(const MyCpp03Allocator<TYPE1>& lhs,
429/// const MyCpp03Allocator<TYPE2>& rhs)
430/// {
431/// return lhs.state() == rhs.state();
432/// }
433///
434/// template <class TYPE1, class TYPE2>
435/// inline
436/// bool operator!=(const MyCpp03Allocator<TYPE1>& lhs,
437/// const MyCpp03Allocator<TYPE2>& rhs)
438/// {
439/// return ! (lhs == rhs);
440/// }
441/// @endcode
442/// Finally we instantiate `MyContainer` using this allocator type and verify
443/// that elements are constructed using the default allocator (because the
444/// allocator is not propagated from the container). We also verify that the
445/// allocator is copied on copy-construction:
446/// @code
447/// int usageExample2()
448/// {
449/// typedef MyCpp03Allocator<MyType> MyTypeAlloc;
450///
451/// MyContainer<MyType, MyTypeAlloc> C1a(MyTypeAlloc(1));
452/// assert((bsl::is_same<MyContainer<MyType, MyTypeAlloc>::allocator_type,
453/// MyTypeAlloc>::value));
454/// assert(C1a.get_allocator() == MyTypeAlloc(1));
455/// assert(C1a.front().allocator() == bslma::Default::defaultAllocator());
456///
457/// MyContainer<MyType, MyTypeAlloc> C2a(C1a);
458/// assert(C2a.get_allocator() == C1a.get_allocator());
459/// assert(C2a.get_allocator() != MyTypeAlloc());
460/// assert(C2a.front().allocator() == bslma::Default::defaultAllocator());
461///
462/// MyType dummy;
463/// MyContainer<MyType, MyTypeAlloc> C1b(dummy, MyTypeAlloc(1));
464/// assert((bsl::is_same<MyContainer<MyType, MyTypeAlloc>::allocator_type,
465/// MyTypeAlloc>::value));
466/// assert(C1b.get_allocator() == MyTypeAlloc(1));
467/// assert(C1b.front().allocator() == bslma::Default::defaultAllocator());
468///
469/// MyContainer<MyType, MyTypeAlloc> C2b(C1b);
470/// assert(C2b.get_allocator() == C1b.get_allocator());
471/// assert(C2b.get_allocator() != MyTypeAlloc());
472/// assert(C2b.front().allocator() == bslma::Default::defaultAllocator());
473///
474/// return 0;
475/// }
476/// @endcode
477/// @}
478/** @} */
479/** @} */
480
481/** @addtogroup bsl
482 * @{
483 */
484/** @addtogroup bslma
485 * @{
486 */
487/** @addtogroup bslma_allocatortraits
488 * @{
489 */
490
491#include <bslscm_version.h>
492
493#include <bslmf_enableif.h>
495#include <bslmf_isempty.h>
496#include <bslmf_issame.h>
497#include <bslmf_util.h>
498#include <bslmf_voidtype.h>
499
501#include <bsls_keyword.h>
502#include <bsls_libraryfeatures.h>
503#include <bsls_util.h> // 'forward<T>(V)'
504
505#if BSLS_COMPILERFEATURES_CPLUSPLUS >= 201703L
506# include <memory> // for `std::allocator_traits`
507#endif
508
509#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
510// clang-format off
511// Include version that can be compiled with C++03
512// Generated on Mon Jan 13 08:31:27 2025
513// Command line: sim_cpp11_features.pl bslma_allocatortraits.h
514
515# define COMPILING_BSLMA_ALLOCATORTRAITS_H
517# undef COMPILING_BSLMA_ALLOCATORTRAITS_H
518
519// clang-format on
520#else
521
522#include <limits>
523
524
525namespace bslma {
526
527
528 // ================================
529 // AllocatorTraits_HasIsAlwaysEqual
530 // ================================
531
532/// This `struct` template provides a mechanism for determining whether a
533/// given (template parameter) `ALLOCATOR_TYPE` defines a nested alias named
534///`is_always_equal`. The static boolean member `value` (nested alias
535/// named `type`) is `true` (`bsl::true_type`) if `ALLOCATOR_TYPE` defines
536/// such an alias, and `false` (`bsl::false_type`) otherwise.
537///
538/// See @ref bslma_allocatortraits
539template <class ALLOC>
541
542 private:
543 // PRIVATE TYPES
544 typedef struct { char d_a; } yes_type;
545 typedef struct { char d_a[2]; } no_type;
546
547 // PRIVATE CLASS METHODS
548
549 /// Return @ref yes_type if the (template parameter) `TYPE` defines a
550 /// nested alias named `is_always_equal`, and `no_type` otherwise.
551 template <class U>
552 static yes_type match(typename U::is_always_equal *);
553 template <class U>
554 static no_type match(...);
555
556 public:
557 // PUBLIC CLASS DATA
558 static const bool value = sizeof(match<ALLOC>(0)) == sizeof(yes_type);
559
560 // PUBLIC TYPES
562};
563
564 // =============================
565 // AllocatorTraits_IsAlwaysEqual
566 // =============================
567
568/// This `struct` template sets the boolean type for the attribute named
569/// `is_always_equal` to the nested type alias in the given (template
570/// parameter) `ALLOC` if `ALLOC` defines such an alias (i.e., if
571/// `true == AllocatorTraits_HasIsAlwaysEqual<ALLOCATOR_TYPE>::value`).
572template <class ALLOC, bool = AllocatorTraits_HasIsAlwaysEqual<ALLOC>::value>
573struct AllocatorTraits_IsAlwaysEqual : public ALLOC::is_always_equal
574{
575};
576
577/// This `struct` template sets the boolean type for the attribute named
578/// `is_always_equal` to `bsl::is_empty<ALLOC>` if the given (template
579/// parameter) `ALLOC` does not define such an alias (i.e., if
580/// `false == AllocatorTraits_HasIsAlwaysEqual<ALLOCATOR_TYPE>::value`).
581template <class ALLOC>
583 : public bsl::is_empty<ALLOC>
584{
585};
586
587 // =====================================
588 // AllocatorTraits_HasSelectOnCopyMethod
589 // =====================================
590
591/// This `struct` template provides a mechanism for determining whether a
592/// given (template parameter) `ALLOCATOR_TYPE` defines a `const` member
593/// function named @ref select_on_container_copy_construction that takes no
594/// arguments and returns an `ALLOCATOR_TYPE` object by value. The static
595/// boolean `value` (nested `type` alias) is `true` (`bsl::true_type`) if
596/// `ALLOCATOR_TYPE` defines such a method, and `false` (`bsl::false_type`)
597/// otherwise.
598///
599/// See @ref bslma_allocatortraits
600template <class ALLOCATOR_TYPE>
602
603 private:
604 typedef struct { char a; } yes_type;
605 typedef struct { char a[2]; } no_type;
606
607 /// This `struct` template provides a mechanism to check if a type
608 /// matches an instance within a SFINAE context.
609 ///
610 /// See @ref bslma_allocatortraits
611 template <class T, T> struct MatchType { };
612
613 template <class T>
614 struct MethodAlias { typedef T (T::*Method)() const; };
615
616 /// Return @ref yes_type if the (template parameter) `TYPE` defines a const
617 /// member function named @ref select_on_container_copy_construction taking
618 /// no arguments and returning a `TYPE` object by value, and `no_type`
619 /// otherwise.
620 template <class TYPE>
621 static yes_type match(MatchType<typename MethodAlias<TYPE>::Method,
622 &TYPE::select_on_container_copy_construction> *);
623 template <class TYPE>
624 static no_type match(...);
625
626 public:
627 static const bool value =
628 sizeof(match<ALLOCATOR_TYPE>(0)) == sizeof(yes_type);
630};
631
632 // ===================================
633 // AllocatorTraits_HasPropOnCopyAssign
634 // ===================================
635
636/// This `struct` template provides a mechanism for determining whether a
637/// given (template parameter) `ALLOCATOR_TYPE` defines a nested alias named
638///@ref propagate_on_container_copy_assignment . The static boolean member
639/// `value` (nested alias named `type`) is `true` (`bsl::true_type`) if
640/// `ALLOCATOR_TYPE` defines such an alias, and `false` (`bsl::false_type`)
641/// otherwise.
642///
643/// See @ref bslma_allocatortraits
644template <class ALLOCATOR_TYPE>
646
647 private:
648 typedef struct { char a; } yes_type;
649 typedef struct { char a[2]; } no_type;
650
651 /// Return @ref yes_type if the (template parameter) `TYPE` defines a
652 /// nested alias named @ref propagate_on_container_copy_assignment , and
653 /// `no_type` otherwise.
654 template <class U>
655 static
656 yes_type match(typename U::propagate_on_container_copy_assignment *);
657 template <class U>
658 static no_type match(...);
659
660 public:
661 static const bool value =
662 sizeof(match<ALLOCATOR_TYPE>(0)) == sizeof(yes_type);
664};
665
666 // ================================
667 // AllocatorTraits_PropOnCopyAssign
668 // ================================
669
670/// This `struct` template sets the boolean type for the attribute named
671/// @ref propagate_on_container_copy_assignment to `bsl::false_type` if the
672/// given (template parameter) `ALLOCATOR_TYPE` does not define such an
673/// alias (i.e.,
674/// `false == AllocatorTraits_HasPropOnCopyAssign<ALLOCATOR_TYPE>::value`).
675template <class ALLOCATOR_TYPE,
680
681/// This `struct` template sets the boolean type for the attribute named
682/// @ref propagate_on_container_copy_assignment to the nested type alias in the
683/// given (template parameter) `ALLOCATOR_TYPE` if `ALLOCATOR_TYPE` defines
684/// such an alias (i.e.,
685/// `true == AllocatorTraits_HasPropOnCopyAssign<ALLOCATOR_TYPE>::value`).
686template <class ALLOC>
688 : public ALLOC::propagate_on_container_copy_assignment
689{
690};
691
692 // ===================================
693 // AllocatorTraits_HasPropOnMoveAssign
694 // ===================================
695
696/// This `struct` template provides a mechanism for determining whether a
697/// given (template parameter) `ALLOCATOR_TYPE` defines a nested alias named
698///@ref propagate_on_container_move_assignment . The static boolean member
699/// `value` (nested alias named `type`) is `true` (`bsl::true_type`) if
700/// `ALLOCATOR_TYPE` defines such an alias, and `false` (`bsl::false_type`)
701/// otherwise.
702///
703/// See @ref bslma_allocatortraits
704template <class ALLOC>
706
707 private:
708 typedef struct { char a; } yes_type;
709 typedef struct { char a[2]; } no_type;
710
711 /// Return @ref yes_type if the (template parameter) `TYPE` defines a
712 /// nested alias named @ref propagate_on_container_move_assignment , and
713 /// `no_type` otherwise.
714 template <class U>
715 static
716 yes_type match(typename U::propagate_on_container_move_assignment *);
717 template <class U>
718 static no_type match(...);
719
720 public:
721 static const bool value = sizeof(match<ALLOC>(0)) == sizeof(yes_type);
723};
724
725 // ================================
726 // AllocatorTraits_PropOnMoveAssign
727 // ================================
728
729/// This `struct` template sets the boolean type for the attribute named
730/// @ref propagate_on_container_move_assignment to `bsl::false_type` if the
731/// given (template parameter) `ALLOCATOR_TYPE` does not define such an
732/// alias (i.e.,
733/// `false == AllocatorTraits_HasPropOnMoveAssign<ALLOCATOR_TYPE>::value`).
734template <class ALLOC,
739
740/// This `struct` template sets the boolean type for the attribute named
741/// @ref propagate_on_container_move_assignment to the nested type alias in the
742/// given (template parameter) `ALLOCATOR_TYPE` if `ALLOCATOR_TYPE` defines
743/// such an alias (i.e.,
744/// `true == AllocatorTraits_HasPropOnMoveAssign<ALLOCATOR_TYPE>::value`).
745template <class ALLOC>
747 : public ALLOC::propagate_on_container_move_assignment
748{
749};
750
751 // =============================
752 // AllocatorTraits_HasPropOnSwap
753 // =============================
754
755/// This `struct` template provides a mechanism for determining whether a
756/// given (template parameter) `ALLOCATOR_TYPE` defines a nested alias named
757///@ref propagate_on_container_swap . The static boolean member `value` (nested
758/// alias named `type`) is `true` (`bsl::true_type`) if `ALLOCATOR_TYPE`
759/// defines such an alias, and `false` (`bsl::false_type`) otherwise.
760///
761/// See @ref bslma_allocatortraits
762template <class ALLOC>
764
765 private:
766 typedef struct { char a; } yes_type;
767 typedef struct { char a[2]; } no_type;
768
769 /// Return @ref yes_type if the (template parameter) `TYPE` defines a
770 /// nested alias named @ref propagate_on_container_swap , and `no_type`
771 /// otherwise.
772 template <class U>
773 static
774 yes_type match(typename U::propagate_on_container_swap *);
775 template <class U>
776 static no_type match(...);
777
778 public:
779 static const bool value = sizeof(match<ALLOC>(0)) == sizeof(yes_type);
781};
782
783 // ==========================
784 // AllocatorTraits_PropOnSwap
785 // ==========================
786
787/// This `struct` template sets the boolean type for the attribute named
788/// @ref propagate_on_container_swap to `bsl::false_type` if the given
789/// (template parameter) `ALLOCATOR_TYPE` does not define such an alias
790/// (i.e., `false == AllocatorTraits_HasPropOnSwap<ALLOCATOR_TYPE>::value`).
791template <class ALLOC, bool = AllocatorTraits_HasPropOnSwap<ALLOC>::value>
795
796/// This `struct` template sets the boolean type for the attribute named
797/// @ref propagate_on_container_swap to the nested type alias in the given
798/// (template parameter) `ALLOCATOR_TYPE` if `ALLOCATOR_TYPE` defines such
799/// an alias (i.e.,
800/// `false == AllocatorTraits_HasPropOnSwap<ALLOCATOR_TYPE>::value`).
801template <class ALLOC>
802struct AllocatorTraits_PropOnSwap<ALLOC, true>
803 : public ALLOC::propagate_on_container_swap
804{
805};
806
807#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE) && \
808 defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) && \
809 defined(BSLS_COMPILERFEATURES_SUPPORT_VARIADIC_TEMPLATES)
810
811 // ==================================
812 // AllocatorTraits_HasConstructMethod
813 // ==================================
814
815template <class T, class Return, class... Args>
816struct AllocatorTraits_HasConstructMethod {
817 private:
818 template <class U>
819 static auto match(U *) ->
821 bslmf::Util::declval<Args>()...)),
822 Return>::type;
823 template <class>
824 static bsl::false_type match(...);
825
826 public:
827 typedef decltype(match<T>(0)) type;
828 static const bool value = type::value;
829};
830
831 // ================================
832 // AllocatorTraits_HasDestroyMethod
833 // ================================
834
835template <class T, class Return, class... Args>
836struct AllocatorTraits_HasDestroyMethod {
837 private:
838 template <class U>
839 static auto match(U *) ->
841 bslmf::Util::declval<Args>()...)),
842 Return>::type;
843 template <class>
844 static bsl::false_type match(...);
845
846 public:
847 typedef decltype(match<T>(0)) type;
848 static const bool value = type::value;
849};
850
851#endif
852
853 // ===========================
854 // AllocatorTraits_PointerType
855 // ===========================
856
857template <class T, class = void>
859 typedef typename T::value_type *type;
860};
861
862
863template <class T>
864struct AllocatorTraits_PointerType<T, BSLMF_VOIDTYPE(typename T::pointer)> {
865 typedef typename T::pointer type;
866};
867
868 // ================================
869 // AllocatorTraits_ConstPointerType
870 // ================================
871
872template <class T, class = void>
874 /// should be pointer_traits::rebind of template above
875 typedef const typename T::value_type *type;
876};
877
878
879template <class T>
881 T,
882 BSLMF_VOIDTYPE(typename T::const_pointer)> {
883 typedef typename T::const_pointer type;
884};
885
886
887 // ===============================
888 // AllocatorTraits_VoidPointerType
889 // ===============================
890
891template <class T, class = void>
893 /// should be pointer_traits::rebind of template above
894 typedef void *type;
895};
896
897
898template <class T>
900 T,
901 BSLMF_VOIDTYPE(typename T::void_pointer)> {
902 typedef typename T::void_pointer type;
903};
904
905 // ====================================
906 // AllocatorTraits_ConstVoidPointerType
907 // ====================================
908
909template <class T, class = void>
911 /// should be pointer_traits::rebind of template above
912 typedef const void *type;
913};
914
915
916template <class T>
918 T,
919 BSLMF_VOIDTYPE(typename T::const_void_pointer)> {
920 typedef typename T::const_void_pointer type;
921};
922
923 // ========================
924 // AllocatorTraits_SizeType
925 // ========================
926
927template <class T, class = void>
929 typedef std::size_t type;
930};
931
932
933template <class T>
934struct AllocatorTraits_SizeType<T, BSLMF_VOIDTYPE(typename T::size_type)> {
935 typedef typename T::size_type type;
936};
937
938 // ==============================
939 // AllocatorTraits_DifferenceType
940 // ==============================
941
942/// should be pointer_traits::rebind of template above
943///
944/// See @ref bslma_allocatortraits
945template <class T, class = void>
947 typedef std::ptrdiff_t type;
948
949};
950
951
952template <class T>
954 T,
955 BSLMF_VOIDTYPE(typename T::difference_type)> {
956 typedef typename T::difference_type type;
957};
958
959 // ===========================
960 // AllocatorTraits_RebindFront
961 // ===========================
962
963#if defined(BSLS_COMPILERFEATURES_SUPPORT_VARIADIC_TEMPLATES)
964/// There shall be no member named `type` unless T is a class template with
965/// only type parameters.
966///
967/// See @ref bslma_allocatortraits
968template <class T, class U>
970};
971
972template <template <class, class...> class ALLOC,
973 class T,
974 class ...ARGS,
975 class U>
976struct AllocatorTraits_RebindFront<ALLOC<T, ARGS...>, U> {
977 using type = ALLOC<U, ARGS...>;
978};
979#else
980template <class T, class U>
982 // There shall be no member named 'type' unless T is a class template with
983 // only type parameters.
984};
985
986template <template <class> class ALLOC,
987 class T,
988 class U>
989struct AllocatorTraits_RebindFront<ALLOC<T>, U> {
990 typedef ALLOC<U> type;
991};
992#endif
993
994 // ===========================
995 // AllocatorTraits_RebindAlloc
996 // ===========================
997
998/// should be pointer_traits::rebind of template above
999///
1000/// See @ref bslma_allocatortraits
1001template <class T, class U, class = void>
1005
1006template <class T, class U>
1008 T,
1009 U,
1010 BSLMF_VOIDTYPE(typename T::template rebind<U>::other)> {
1011 typedef typename T::template rebind<U>::other type;
1012};
1013
1014 // ===========================
1015 // AllocatorTraits_CallMaxSize
1016 // ===========================
1017
1018#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)
1019template <class T, class = void>
1020struct AllocatorTraits_CallMaxSize {
1021
1022 // PUBLIC TYPES
1023 typedef typename AllocatorTraits_SizeType<T>::type SizeType;
1024
1025 // PUBLIC CLASS METHODS
1026
1027 /// Return the maximum size of the specified (template) parameter `T`.
1028 /// Also note that this method is defined inline to work around a
1029 /// Windows compiler bug with SFINAE functions.
1030 static SizeType max_size(const T &)
1031 {
1032 return std::numeric_limits<SizeType>::max() /
1033 sizeof(typename T::value_type);
1034 }
1035};
1036
1037// Due to the dependence on expression SFINAE to detect the presence of a
1038// @ref max_size member of the allocator, this is only done on more modern
1039// platforms.
1040template <class T>
1041struct AllocatorTraits_CallMaxSize<
1042 T,
1043 BSLMF_VOIDTYPE(decltype(bslmf::Util::declval<T>().max_size()))> {
1044
1045 // PUBLIC TYPES
1046 typedef typename AllocatorTraits_SizeType<T>::type SizeType;
1047
1048 // PUBLIC CLASS METHODS
1049
1050 /// Return the maximum size of the specified `alloc`. Also note that
1051 /// this method is defined inline to work around a Windows compiler bug
1052 /// with SFINAE functions.
1053 static SizeType max_size(const T &alloc)
1054 {
1055 return alloc.max_size();
1056 }
1057};
1058#endif
1059
1060} // close namespace bslma
1061
1062
1063namespace bsl {
1064
1065 // ======================
1066 // class allocator_traits
1067 // ======================
1068
1069/// This class supports the complete interface of the C++11
1070/// `allocator_traits` class template, which provides a uniform mechanism
1071/// for accessing nested types within, and operations on, any
1072/// standard-conforming allocator. A specialization of this class template
1073/// for `bsl::allocator` provides support for Bloomberg's `bslma` allocator
1074/// model (see the @ref bslma_bslallocator component for more details). In
1075/// C++11 compilation environments, the `construct` methods forward to the
1076/// allocator's `construct` method if such a method matching the (variable
1077/// number of) specified constructor arguments exists; otherwise, the
1078/// `construct` method falls back to invoking the constructor of the element
1079/// type directly. In C++03 compilation environments, there is no reliable
1080/// way to detect if the type provide a method that matches a (variable
1081/// number of) specified arguments; therefore, we require that standard
1082/// allocator types define `construct` methods taking a variable number of
1083/// arguments in those environments. This implementation is not
1084/// fully-standard-conforming in that it does not support deduce data types
1085/// that are not specified in the allocator.
1086///
1087/// See @ref bslma_allocatortraits
1088template <class ALLOCATOR_TYPE>
1090
1091 private:
1092
1093 typedef typename BloombergLP::bslma::AllocatorTraits_HasSelectOnCopyMethod<
1094 ALLOCATOR_TYPE>::type DelegateSelectMethod;
1095
1096 /// Return the result of invoking the
1097 /// @ref select_on_container_copy_construction method on the specified
1098 /// `stdAllocator`.
1099 static
1100 ALLOCATOR_TYPE selectOnCopyConstruct(const ALLOCATOR_TYPE& stdAllocator,
1101 true_type);
1102
1103 /// Return the specified `stdAllocator`.
1104 /// \note Note that this behavior
1105 /// enforces a default policy of propagating the allocator on copy
1106 /// construction when using a standard allocator.
1107 static
1108 ALLOCATOR_TYPE selectOnCopyConstruct(const ALLOCATOR_TYPE& stdAllocator,
1109 false_type);
1110
1111#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE) && \
1112 defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) && \
1113 defined(BSLS_COMPILERFEATURES_SUPPORT_VARIADIC_TEMPLATES)
1114 /// Construct an object of (template parameter) type `ELEMENT_TYPE` at
1115 /// the specified `elementAddr`, either by 1) calling the `construct`
1116 /// method on `basicAllocator` with `elemAddr` and the specified
1117 /// (variable number of) `arguments` if the (template parameter) type
1118 /// `ALLOCATOR_TYPE` defines such a method, or 2) forwarding the
1119 /// specified (variable number of) `arguments` to the constructor of
1120 /// `ELEMENT_TYPE` directly (and ignoring `basicAllocator`) otherwise.
1121 ///
1122 /// \pre The behavior is undefined unless `elementAddr` refers to valid,
1123 /// uninitialized storage.
1124 template <class ELEMENT_TYPE, class... Args>
1125 static typename bsl::enable_if<
1126 BloombergLP::bslma::AllocatorTraits_HasConstructMethod<ALLOCATOR_TYPE,
1127 void,
1128 ELEMENT_TYPE *,
1129 Args...>::value,
1130 void>::type
1131 privateConstruct(ALLOCATOR_TYPE& basicAllocator,
1132 ELEMENT_TYPE *elementAddr,
1133 Args&&... arguments);
1134 template <class ELEMENT_TYPE, class... Args>
1135 static typename bsl::enable_if<
1136 !BloombergLP::bslma::AllocatorTraits_HasConstructMethod<
1137 ALLOCATOR_TYPE,
1138 void,
1139 ELEMENT_TYPE *,
1140 Args...>::value,
1141 void>::type
1142 privateConstruct(ALLOCATOR_TYPE& basicAllocator,
1143 ELEMENT_TYPE *elementAddr,
1144 Args&&... arguments);
1145
1146 template <class ELEMENT_TYPE>
1147 static typename bsl::enable_if<
1148 BloombergLP::bslma::AllocatorTraits_HasDestroyMethod<
1149 ALLOCATOR_TYPE,
1150 void,
1151 ELEMENT_TYPE *>::value,
1152 void>::type
1153 privateDestroy(ALLOCATOR_TYPE& basicAllocator, ELEMENT_TYPE *elementAddr);
1154
1155 /// Destroy the object of (template parameter) type `ELEMENT_TYPE` at
1156 /// the specified `elementAddr`, either by 1) calling the `destroy`
1157 /// method on `basicAllocator` with `elemAddr` as the sole argument if
1158 /// the (template parameter) type `ALLOCATOR_TYPE` defines such a
1159 /// method, or 2) calling the destructor directly on `elementAddr` (and
1160 /// ignoring `basicAllocator`) otherwise.
1161 ///
1162 /// \pre The behavior is undefined unless `elementAddr` refers to a valid, constructed object.
1163 template <class ELEMENT_TYPE>
1164 static typename bsl::enable_if<
1165 !BloombergLP::bslma::AllocatorTraits_HasDestroyMethod<
1166 ALLOCATOR_TYPE,
1167 void,
1168 ELEMENT_TYPE *>::value,
1169 void>::type
1170 privateDestroy(ALLOCATOR_TYPE& basicAllocator, ELEMENT_TYPE *elementAddr);
1171#endif
1172
1173 public:
1174 // PUBLIC TYPES
1175 typedef ALLOCATOR_TYPE allocator_type;
1176 typedef typename ALLOCATOR_TYPE::value_type value_type;
1177
1178 typedef typename
1179 BloombergLP::bslma::AllocatorTraits_PointerType<ALLOCATOR_TYPE>::type
1181 typedef typename
1182 BloombergLP::bslma::AllocatorTraits_ConstPointerType<ALLOCATOR_TYPE>::type
1184 typedef typename
1185 BloombergLP::bslma::AllocatorTraits_VoidPointerType<ALLOCATOR_TYPE>::type
1187 typedef typename BloombergLP::bslma::
1188 AllocatorTraits_ConstVoidPointerType<ALLOCATOR_TYPE>::type
1190
1191 typedef typename
1192 BloombergLP::bslma::AllocatorTraits_DifferenceType<ALLOCATOR_TYPE>::type
1194 typedef typename
1195 BloombergLP::bslma::AllocatorTraits_SizeType<ALLOCATOR_TYPE>::type
1197
1198#ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
1199 template <class ELEMENT_TYPE>
1200 using rebind_alloc = typename
1201 BloombergLP::bslma::AllocatorTraits_RebindAlloc<ALLOCATOR_TYPE,
1202 ELEMENT_TYPE>::type;
1203
1204 template <class ELEMENT_TYPE>
1206#else // !BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
1207 template <class ELEMENT_TYPE>
1209 : BloombergLP::bslma::AllocatorTraits_RebindAlloc<ALLOCATOR_TYPE,
1210 ELEMENT_TYPE>::type
1211 {
1212 // Note that this class attempts to emulate an alias template, but is
1213 // not complete. In general, code that must support C++03 should use
1214 // 'rebind_traits<ELEMENT_TYPE>::allocator_type' instead of
1215 // 'rebind_alloc<ELEMENT_TYPE>' because that nested typedef is the
1216 // preferred actual allocator type and not a subclass of the desired
1217 // type.
1218
1219 typedef typename BloombergLP::bslma::
1220 AllocatorTraits_RebindAlloc<ALLOCATOR_TYPE, ELEMENT_TYPE>::type
1222
1223 template <typename ARG>
1224 rebind_alloc(const ARG& allocatorArg)
1225 // Convert from anything that can be used to construct the base
1226 // type. This might be better if SFINAE-ed out using
1227 // 'is_convertible', but stressing older compilers more seems
1228 // unwise.
1229 : allocator_type(allocatorArg)
1230 {
1231 }
1232 };
1233
1234 template <class ELEMENT_TYPE>
1235 struct rebind_traits : allocator_traits<typename allocator_traits::template
1236 rebind_alloc<ELEMENT_TYPE>::allocator_type>
1237 {
1238 };
1239#endif // !BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
1240
1241 // Allocation functions
1242
1243 /// Return `basicAllocator.allocate(n)`.
1244 static pointer allocate(ALLOCATOR_TYPE& basicAllocator, size_type n);
1245
1246 /// Return `basicAllocator.allocate(n, hint)`.
1247 static pointer allocate(ALLOCATOR_TYPE& basicAllocator,
1248 size_type n,
1249 const_void_pointer hint);
1250
1251 /// Invoke `basicAllocator.deallocate(elementAddr, n)`.
1252 ///
1253 /// \pre The behavior is undefined unless the specified `elementAddr` was returned from a
1254 /// prior call to the `allocate` method of an allocator that compares
1255 /// equal to the specified `allocator`, and has not yet been passed to a
1256 /// `deallocate` call of such an allocator object.
1257 static void deallocate(ALLOCATOR_TYPE& basicAllocator,
1258 pointer elementAddr,
1259 size_type n);
1260
1261 // Element creation functions
1262
1263#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=14
1264
1265 /// Construct an object of (template parameter) type `ELEMENT_TYPE` at
1266 /// the specified `elementAddr`, either by 1) calling the `construct`
1267 /// method on `basicAllocator` with `elemAddr` and the specified
1268 /// (variable number of) `arguments` if the (template parameter) type
1269 /// `ALLOCATOR_TYPE` defines such a method, or 2) forwarding the
1270 /// specified (variable number of) `arguments` to the constructor of
1271 /// `ELEMENT_TYPE` directly (and ignoring `basicAllocator`) otherwise.
1272 ///
1273 /// \pre The behavior is undefined unless `elementAddr` refers to valid,
1274 /// uninitialized storage.
1275 template <class ELEMENT_TYPE, class... Args>
1276 static void construct(ALLOCATOR_TYPE& basicAllocator,
1277 ELEMENT_TYPE *elementAddr,
1278 Args&&... arguments);
1279#endif
1280
1281 /// Destroy the object of (template parameter) type `ELEMENT_TYPE` at
1282 /// the specified `elementAddr`, either by 1) calling the `destroy`
1283 /// method on `basicAllocator` with `elemAddr` as the sole argument if
1284 /// the (template parameter) type `ALLOCATOR_TYPE` defines such a
1285 /// method, or 2) calling the destructor directly on `elementAddr` (and
1286 /// ignoring `basicAllocator`) otherwise.
1287 ///
1288 /// \pre The behavior is undefined unless `elementAddr` refers to a valid, constructed object.
1289 template <class ELEMENT_TYPE>
1290 static void destroy(ALLOCATOR_TYPE& basicAllocator,
1291 ELEMENT_TYPE *elementAddr);
1292
1293 /// Return the largest number of `value_type` objects that could
1294 /// reasonably be returned by a single invocation of `allocate` for the
1295 /// specified `allocator`, i.e., `allocator.max_size()`.
1296 static size_type max_size(const ALLOCATOR_TYPE& basicAllocator)
1298
1299 // Allocator propagation traits
1300
1301 /// Return a copy of the allocator that should be used to copy-
1302 /// construct one container from another container whose allocator is
1303 /// the specified `rhs`. If the parameterized `ALLOCATOR_TYPE` defines
1304 /// a method @ref select_on_container_copy_construction , this function
1305 /// returns the result of calling that method on `rhs`; otherwise, this
1306 /// method enforces the default policy of propagating the allocator on
1307 /// copy construction, as is standard practice for standard allocators (i.e., returns `rhs`).
1308 ///
1309 /// \note Note that the specialization of this class
1310 /// template for `bsl::allocator` (in the @ref bslma_bslallocator
1311 /// component) provides the alternate default behavior of *not*
1312 /// propagating the allocator on copy construction (i.e., returning a
1313 /// default-constructed allocator object).
1314 static ALLOCATOR_TYPE
1316
1317 /// Identical to, or derived from `true_type` if two allocators of
1318 /// parameterized `ALLOCATOR_TYPE` always compare equal; otherwise
1319 /// identical to or derived from `false_type`. This type is
1320 /// `ALLOCATOR_TYPE::is_always_equal` if such a type is defined, and
1321 /// `is_empty<ALLOCATOR_TYPE>` otherwise.
1322 typedef typename BloombergLP::bslma::AllocatorTraits_IsAlwaysEqual<
1323 ALLOCATOR_TYPE>::type is_always_equal;
1324
1325 /// Identical to, or derived from `true_type` if an allocator of
1326 /// parameterized `ALLOCATOR_TYPE` should be copied when a container
1327 /// using that `ALLOCATOR_TYPE` is copy-assigned; otherwise identical to
1328 /// or derived from `false_type`. This type is
1329 /// `ALLOCATOR_TYPE::propagate_on_container_copy_assignment` if such a
1330 /// type is defined, and `false_type` otherwise.
1331 typedef typename BloombergLP::bslma::AllocatorTraits_PropOnCopyAssign<
1333
1334 /// Identical to, or derived from `true_type` if an allocator of
1335 /// parameterized `ALLOCATOR_TYPE` should be moved when a container
1336 /// using that `ALLOCATOR_TYPE` is move-assigned; otherwise identical to
1337 /// or derived from `false_type`. This type is
1338 /// `ALLOCATOR_TYPE::propagate_on_container_move_assignment` if such a
1339 /// type is defined, and `false_type` otherwise.
1340 typedef typename BloombergLP::bslma::AllocatorTraits_PropOnMoveAssign<
1342
1343 /// Identical to, or derived from `true_type` if the allocators of
1344 /// parameterized `ALLOCATOR_TYPE` should be swapped when containers
1345 /// using that `ALLOCATOR_TYPE` are swapped; otherwise identical to or
1346 /// derived from `false_type`. This type is
1347 /// `ALLOCATOR_TYPE::propagate_on_container_swap` if such a type is
1348 /// defined, and `false_type` otherwise.
1349 typedef typename BloombergLP::bslma::AllocatorTraits_PropOnSwap<
1350 ALLOCATOR_TYPE>::type propagate_on_container_swap;
1351};
1352
1353 // ========================================
1354 // class allocator_traits<ALLOCATOR_TYPE *>
1355 // ========================================
1356
1357/// TBD: improve comment This is an empty class specialization of
1358/// `allocator_traits` for pointer types that (intentionally) does not
1359/// define any of the traits typedefs. It's needed in order make
1360/// unambiguous function overloads that take both a standard allocator by
1361/// value and a `bslma::Allocator *`. By using the typedefs defined in
1362/// `allocator_traits` in the signature of functions taking standard
1363/// allocators, we can ensure that those overloads are not considered when
1364/// using `bslma`-style allocators.
1365template <class ALLOCATOR_TYPE>
1366struct allocator_traits<ALLOCATOR_TYPE *> {
1367};
1368
1369#if BSLS_COMPILERFEATURES_CPLUSPLUS >= 201703L
1370// Since C++17 many of the `std::allocator` members are deprecated (and removed
1371// in C++20). C++23 deprecates type name members and C++26 removes them. The
1372// clang compiler on Darwin warns about any mention of those names in C++17 so
1373// this header file was producing many warnings. The specialization below
1374// "disconnects" the allocator traits of `std::allocator` from our own
1375// implementation and so it avoids not only warnings but possible other hassles
1376// as the `std::allocator` interface is morphing.
1377//
1378// Note that we are using the standard traits (in place of ours) only on C++17
1379// or later compilers and not C++11 (when `std::allocator_traits` appeared).
1380// The reason for this is that our `bsl::allocator_traits` supports
1381// `allocator_traits::is_always_equal` from C++17 in a backwards compatible
1382// manner so we cannot use pre-C++17 standard implementation that does not have
1383// that.
1384template <class ALLOCATOR_TYPE>
1385struct allocator_traits<std::allocator<ALLOCATOR_TYPE> >
1386: std::allocator_traits<std::allocator<ALLOCATOR_TYPE> > {
1387};
1388
1389#endif
1390
1391} // close namespace bsl
1392
1393// ============================================================================
1394// INLINE AND TEMPLATE STATIC MEMBER FUNCTION DEFINITIONS
1395// ============================================================================
1396
1397namespace bsl {
1398
1399 // ----------------------
1400 // class allocator_traits
1401 // ----------------------
1402
1403template <class ALLOCATOR_TYPE>
1404inline
1405ALLOCATOR_TYPE allocator_traits<ALLOCATOR_TYPE>::selectOnCopyConstruct(
1406 const ALLOCATOR_TYPE& stdAllocator,
1407 true_type)
1408{
1409 return stdAllocator.select_on_container_copy_construction();
1410}
1411
1412template <class ALLOCATOR_TYPE>
1413inline
1414ALLOCATOR_TYPE allocator_traits<ALLOCATOR_TYPE>::selectOnCopyConstruct(
1415 const ALLOCATOR_TYPE& stdAllocator,
1416 false_type)
1417{
1418 return stdAllocator;
1419}
1420
1421#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE) && \
1422 defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) && \
1423 defined(BSLS_COMPILERFEATURES_SUPPORT_VARIADIC_TEMPLATES)
1424template <class ALLOCATOR_TYPE>
1425template <class ELEMENT_TYPE, class... Args>
1426inline
1427typename bsl::enable_if<
1428 BloombergLP::bslma::AllocatorTraits_HasConstructMethod<ALLOCATOR_TYPE,
1429 void,
1430 ELEMENT_TYPE *,
1431 Args...>::value,
1432 void>::type
1433allocator_traits<ALLOCATOR_TYPE>::privateConstruct(
1434 ALLOCATOR_TYPE& basicAllocator,
1435 ELEMENT_TYPE *elementAddr,
1436 Args&&... arguments)
1437{
1438 basicAllocator.construct(
1439 elementAddr, BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
1440}
1441
1442template <class ALLOCATOR_TYPE>
1443template <class ELEMENT_TYPE, class... Args>
1444inline
1445typename bsl::enable_if<
1446 !BloombergLP::bslma::AllocatorTraits_HasConstructMethod<ALLOCATOR_TYPE,
1447 void,
1448 ELEMENT_TYPE *,
1449 Args...>::value,
1450 void>::type
1451allocator_traits<ALLOCATOR_TYPE>::privateConstruct(ALLOCATOR_TYPE&,
1452 ELEMENT_TYPE *elementAddr,
1453 Args&&... arguments)
1454{
1455 ::new (static_cast<void *>(elementAddr))
1456 ELEMENT_TYPE(BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
1457}
1458
1459template <class ALLOCATOR_TYPE>
1460template <class ELEMENT_TYPE>
1461inline
1462typename bsl::enable_if<BloombergLP::bslma::AllocatorTraits_HasDestroyMethod<
1463 ALLOCATOR_TYPE,
1464 void,
1465 ELEMENT_TYPE *>::value,
1466 void>::type
1467allocator_traits<ALLOCATOR_TYPE>::privateDestroy(
1468 ALLOCATOR_TYPE& basicAllocator,
1469 ELEMENT_TYPE *elementAddr)
1470{
1471 basicAllocator.destroy(elementAddr);
1472}
1473
1474template <class ALLOCATOR_TYPE>
1475template <class ELEMENT_TYPE>
1476inline
1477typename bsl::enable_if<!BloombergLP::bslma::AllocatorTraits_HasDestroyMethod<
1478 ALLOCATOR_TYPE,
1479 void,
1480 ELEMENT_TYPE *>::value,
1481 void>::type
1482allocator_traits<ALLOCATOR_TYPE>::privateDestroy(ALLOCATOR_TYPE&,
1483 ELEMENT_TYPE *elementAddr)
1484{
1485 elementAddr->~ELEMENT_TYPE();
1486}
1487#endif
1488
1489// Allocation functions
1490
1491template <class ALLOCATOR_TYPE>
1492inline
1494allocator_traits<ALLOCATOR_TYPE>::allocate(ALLOCATOR_TYPE& basicAllocator,
1495 size_type n)
1496{
1497 return basicAllocator.allocate(n);
1498}
1499
1500template <class ALLOCATOR_TYPE>
1501inline
1503allocator_traits<ALLOCATOR_TYPE>::allocate(ALLOCATOR_TYPE& basicAllocator,
1504 size_type n,
1505 const_void_pointer hint)
1506{
1507 return basicAllocator.allocate(n, hint);
1508}
1509
1510template <class ALLOCATOR_TYPE>
1511inline
1512void
1514 pointer elementAddr,
1515 size_type n)
1516{
1517 basicAllocator.deallocate(elementAddr, n);
1518}
1519
1520// ELEMENT CREATION FUNCTIONS
1521
1522#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1523template <class ALLOCATOR_TYPE>
1524template <class ELEMENT_TYPE, class... Args>
1525inline
1526void
1527allocator_traits<ALLOCATOR_TYPE>::construct(ALLOCATOR_TYPE& basicAllocator,
1528 ELEMENT_TYPE *elementAddr,
1529 Args&&... arguments)
1530{
1531#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)
1532 privateConstruct(basicAllocator,
1533 elementAddr,
1534 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
1535#else
1536 // Cannot sniff out whether 'basicAllocator.construct(...)' is valid in
1537 // C++03, but allocators are required to have a 'construct' method, so just
1538 // call it.
1539 basicAllocator.construct(
1540 elementAddr, BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
1541#endif
1542}
1543#endif
1544
1545template <class ALLOCATOR_TYPE>
1546template <class ELEMENT_TYPE>
1547inline
1548void
1550 ELEMENT_TYPE *elementAddr)
1551{
1552// For full C++11 compatibility, this should check for the well-formedness of
1553// the allocator-specific code that is commented out below (via some SFINAE
1554// trickery), and switch to the 'DestructionUtil' implementation only if the
1555// 'destroy' member function is not available.
1556
1557// allocator.destroy(elementAddr);
1558#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE) && \
1559 defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
1560 privateDestroy(stdAllocator, elementAddr);
1561#else
1562 elementAddr->~ELEMENT_TYPE();
1563 (void) stdAllocator;
1564#endif
1565}
1566
1567template <class ALLOCATOR_TYPE>
1568inline
1571 const ALLOCATOR_TYPE& basicAllocator) BSLS_KEYWORD_NOEXCEPT
1572{
1573#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)
1574 return BloombergLP::bslma::
1575 AllocatorTraits_CallMaxSize<ALLOCATOR_TYPE>::max_size(basicAllocator);
1576#else
1577 // Cannot sniff out whether 'basicAllocator.max_size()' is valid in C++03,
1578 // but for now require that allocators have a @ref max_size method and just
1579 // call it.
1580 return basicAllocator.max_size();
1581#endif
1582}
1583
1584template <class ALLOCATOR_TYPE>
1585inline
1586ALLOCATOR_TYPE
1588 const ALLOCATOR_TYPE& rhs)
1589{
1590 return selectOnCopyConstruct(rhs, DelegateSelectMethod());
1591}
1592
1593} // close namespace bsl
1594
1595#endif // End C++11 code
1596
1597#endif // ! defined(INCLUDED_BSLMA_ALLOCATORTRAITS)
1598
1599// ----------------------------------------------------------------------------
1600// Copyright 2013 Bloomberg Finance L.P.
1601//
1602// Licensed under the Apache License, Version 2.0 (the "License");
1603// you may not use this file except in compliance with the License.
1604// You may obtain a copy of the License at
1605//
1606// http://www.apache.org/licenses/LICENSE-2.0
1607//
1608// Unless required by applicable law or agreed to in writing, software
1609// distributed under the License is distributed on an "AS IS" BASIS,
1610// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1611// See the License for the specific language governing permissions and
1612// limitations under the License.
1613// ----------------------------- END-OF-FILE ----------------------------------
1614
1615/** @} */
1616/** @} */
1617/** @} */
Definition bslma_bslallocator.h:588
#define BSLMF_VOIDTYPE(ARG)
Definition bslmf_voidtype.h:343
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
Definition bdlat_valuetypefunctions.h:939
integral_constant< bool, false > false_type
Definition bslmf_integralconstant.h:290
integral_constant< bool, true > true_type
Definition bslmf_integralconstant.h:296
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
Definition baljsn_encoder_testtypes.h:76
Definition bdlbb_blob.h:579
Definition bdldfp_decimal.h:5549
Definition bslma_allocatortraits.h:1211
rebind_alloc(const ARG &allocatorArg)
Definition bslma_allocatortraits.h:1224
BloombergLP::bslma::AllocatorTraits_RebindAlloc< ALLOCATOR_TYPE, ELEMENT_TYPE >::type allocator_type
Definition bslma_allocatortraits.h:1221
Definition bslma_allocatortraits.h:1237
Definition bslma_allocatortraits.h:1089
static pointer allocate(ALLOCATOR_TYPE &basicAllocator, size_type n)
Return basicAllocator.allocate(n).
Definition bslma_allocatortraits.h:1494
BloombergLP::bslma::AllocatorTraits_ConstPointerType< ALLOCATOR_TYPE >::type const_pointer
Definition bslma_allocatortraits.h:1183
BloombergLP::bslma::AllocatorTraits_VoidPointerType< ALLOCATOR_TYPE >::type void_pointer
Definition bslma_allocatortraits.h:1186
BloombergLP::bslma::AllocatorTraits_PropOnCopyAssign< ALLOCATOR_TYPE >::type propagate_on_container_copy_assignment
Definition bslma_allocatortraits.h:1332
BloombergLP::bslma::AllocatorTraits_PropOnMoveAssign< ALLOCATOR_TYPE >::type propagate_on_container_move_assignment
Definition bslma_allocatortraits.h:1341
static ALLOCATOR_TYPE select_on_container_copy_construction(const ALLOCATOR_TYPE &rhs)
Definition bslma_allocatortraits.h:1587
BloombergLP::bslma::AllocatorTraits_SizeType< ALLOCATOR_TYPE >::type size_type
Definition bslma_allocatortraits.h:1196
static void construct(ALLOCATOR_TYPE &basicAllocator, ELEMENT_TYPE *elementAddr, Args &&... arguments)
Definition bslma_allocatortraits.h:1527
static pointer allocate(ALLOCATOR_TYPE &basicAllocator, size_type n, const_void_pointer hint)
Return basicAllocator.allocate(n, hint).
Definition bslma_allocatortraits.h:1503
static size_type max_size(const ALLOCATOR_TYPE &basicAllocator) BSLS_KEYWORD_NOEXCEPT
Definition bslma_allocatortraits.h:1570
BloombergLP::bslma::AllocatorTraits_PointerType< ALLOCATOR_TYPE >::type pointer
Definition bslma_allocatortraits.h:1180
static void destroy(ALLOCATOR_TYPE &basicAllocator, ELEMENT_TYPE *elementAddr)
Definition bslma_allocatortraits.h:1549
BloombergLP::bslma::AllocatorTraits_IsAlwaysEqual< ALLOCATOR_TYPE >::type is_always_equal
Definition bslma_allocatortraits.h:1323
static void deallocate(ALLOCATOR_TYPE &basicAllocator, pointer elementAddr, size_type n)
Definition bslma_allocatortraits.h:1513
BloombergLP::bslma::AllocatorTraits_PropOnSwap< ALLOCATOR_TYPE >::type propagate_on_container_swap
Definition bslma_allocatortraits.h:1350
ALLOCATOR_TYPE allocator_type
Definition bslma_allocatortraits.h:1175
BloombergLP::bslma::AllocatorTraits_ConstVoidPointerType< ALLOCATOR_TYPE >::type const_void_pointer
Definition bslma_allocatortraits.h:1189
BloombergLP::bslma::AllocatorTraits_DifferenceType< ALLOCATOR_TYPE >::type difference_type
Definition bslma_allocatortraits.h:1193
ALLOCATOR_TYPE::value_type value_type
Definition bslma_allocatortraits.h:1176
Definition bslmf_enableif.h:530
Definition bslmf_integralconstant.h:261
Definition bslmf_isempty.h:319
Definition bslmf_issame.h:146
Definition bslma_allocatortraits.h:873
const T::value_type * type
should be pointer_traits::rebind of template above
Definition bslma_allocatortraits.h:875
Definition bslma_allocatortraits.h:910
const void * type
should be pointer_traits::rebind of template above
Definition bslma_allocatortraits.h:912
Definition bslma_allocatortraits.h:946
std::ptrdiff_t type
Definition bslma_allocatortraits.h:947
Definition bslma_allocatortraits.h:540
static const bool value
Definition bslma_allocatortraits.h:558
bsl::integral_constant< bool, value > type
Definition bslma_allocatortraits.h:561
Definition bslma_allocatortraits.h:645
static const bool value
Definition bslma_allocatortraits.h:661
bsl::integral_constant< bool, value > type
Definition bslma_allocatortraits.h:663
Definition bslma_allocatortraits.h:705
bsl::integral_constant< bool, value > type
Definition bslma_allocatortraits.h:722
static const bool value
Definition bslma_allocatortraits.h:721
Definition bslma_allocatortraits.h:763
bsl::integral_constant< bool, value > type
Definition bslma_allocatortraits.h:780
static const bool value
Definition bslma_allocatortraits.h:779
Definition bslma_allocatortraits.h:601
bsl::integral_constant< bool, value > type
Definition bslma_allocatortraits.h:629
static const bool value
Definition bslma_allocatortraits.h:627
Definition bslma_allocatortraits.h:574
Definition bslma_allocatortraits.h:858
T::value_type * type
Definition bslma_allocatortraits.h:859
Definition bslma_allocatortraits.h:678
Definition bslma_allocatortraits.h:737
Definition bslma_allocatortraits.h:793
T::template rebind< U >::other type
Definition bslma_allocatortraits.h:1011
Definition bslma_allocatortraits.h:1002
AllocatorTraits_RebindFront< T, U >::type type
Definition bslma_allocatortraits.h:1003
ALLOC< U > type
Definition bslma_allocatortraits.h:990
Definition bslma_allocatortraits.h:981
T::size_type type
Definition bslma_allocatortraits.h:935
Definition bslma_allocatortraits.h:928
std::size_t type
Definition bslma_allocatortraits.h:929
Definition bslma_allocatortraits.h:892
void * type
should be pointer_traits::rebind of template above
Definition bslma_allocatortraits.h:894