BDE 4.14.0 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/// `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_util.h> // 'forward<T>(V)'
503
504#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
505// Include version that can be compiled with C++03
506// Generated on Fri May 13 11:05:19 2022
507// Command line: sim_cpp11_features.pl bslma_allocatortraits.h
508# define COMPILING_BSLMA_ALLOCATORTRAITS_H
510# undef COMPILING_BSLMA_ALLOCATORTRAITS_H
511#else
512
513#include <limits>
514
515
516namespace bslma {
517
518
519 // ================================
520 // AllocatorTraits_HasIsAlwaysEqual
521 // ================================
522
523/// This `struct` template provides a mechanism for determining whether a
524/// given (template parameter) `ALLOCATOR_TYPE` defines a nested alias named
525///`is_always_equal`. The static boolean member `value` (nested alias
526/// named `type`) is `true` (`bsl::true_type`) if `ALLOCATOR_TYPE` defines
527/// such an alias, and `false` (`bsl::false_type`) otherwise.
528template <class ALLOC>
530
531 private:
532 // PRIVATE TYPES
533 typedef struct { char d_a; } yes_type;
534 typedef struct { char d_a[2]; } no_type;
535
536 // PRIVATE CLASS METHODS
537
538 /// Return @ref yes_type if the (template parameter) `TYPE` defines a
539 /// nested alias named `is_always_equal`, and `no_type` otherwise.
540 template <class U>
541 static yes_type match(typename U::is_always_equal *);
542 template <class U>
543 static no_type match(...);
544
545 public:
546 // PUBLIC CLASS DATA
547 static const bool value = sizeof(match<ALLOC>(0)) == sizeof(yes_type);
548
549 // PUBLIC TYPES
551};
552
553 // =============================
554 // AllocatorTraits_IsAlwaysEqual
555 // =============================
556
557/// This `struct` template sets the boolean type for the attribute named
558/// `is_always_equal` to the nested type alias in the given (template
559/// parameter) `ALLOC` if `ALLOC` defines such an alias (i.e., if
560/// `true == AllocatorTraits_HasIsAlwaysEqual<ALLOCATOR_TYPE>::value`).
561template <class ALLOC, bool = AllocatorTraits_HasIsAlwaysEqual<ALLOC>::value>
562struct AllocatorTraits_IsAlwaysEqual : public ALLOC::is_always_equal
563{
564};
565
566/// This `struct` template sets the boolean type for the attribute named
567/// `is_always_equal` to `bsl::is_empty<ALLOC>` if the given (template
568/// parameter) `ALLOC` does not define such an alias (i.e., if
569/// `false == AllocatorTraits_HasIsAlwaysEqual<ALLOCATOR_TYPE>::value`).
570template <class ALLOC>
572 : public bsl::is_empty<ALLOC>
573{
574};
575
576 // =====================================
577 // AllocatorTraits_HasSelectOnCopyMethod
578 // =====================================
579
580/// This `struct` template provides a mechanism for determining whether a
581/// given (template parameter) `ALLOCATOR_TYPE` defines a `const` member
582/// function named `select_on_container_copy_construction` that takes no
583/// arguments and returns an `ALLOCATOR_TYPE` object by value. The static
584/// boolean `value` (nested `type` alias) is `true` (`bsl::true_type`) if
585/// `ALLOCATOR_TYPE` defines such a method, and `false` (`bsl::false_type`)
586/// otherwise.
587template <class ALLOCATOR_TYPE>
589
590 private:
591 typedef struct { char a; } yes_type;
592 typedef struct { char a[2]; } no_type;
593
594 /// This `struct` template provides a mechanism to check if a type
595 /// matches an instance within a SFINAE context.
596 template <class T, T> struct MatchType { };
597
598 template <class T>
599 struct MethodAlias { typedef T (T::*Method)() const; };
600
601 /// Return @ref yes_type if the (template parameter) `TYPE` defines a const
602 /// member function named `select_on_container_copy_construction` taking
603 /// no arguments and returning a `TYPE` object by value, and `no_type`
604 /// otherwise.
605 template <class TYPE>
606 static yes_type match(MatchType<typename MethodAlias<TYPE>::Method,
607 &TYPE::select_on_container_copy_construction> *);
608 template <class TYPE>
609 static no_type match(...);
610
611 public:
612 static const bool value =
613 sizeof(match<ALLOCATOR_TYPE>(0)) == sizeof(yes_type);
615};
616
617 // ===================================
618 // AllocatorTraits_HasPropOnCopyAssign
619 // ===================================
620
621/// This `struct` template provides a mechanism for determining whether a
622/// given (template parameter) `ALLOCATOR_TYPE` defines a nested alias named
623///`propagate_on_container_copy_assignment`. The static boolean member
624/// `value` (nested alias named `type`) is `true` (`bsl::true_type`) if
625/// `ALLOCATOR_TYPE` defines such an alias, and `false` (`bsl::false_type`)
626/// otherwise.
627template <class ALLOCATOR_TYPE>
629
630 private:
631 typedef struct { char a; } yes_type;
632 typedef struct { char a[2]; } no_type;
633
634 /// Return @ref yes_type if the (template parameter) `TYPE` defines a
635 /// nested alias named `propagate_on_container_copy_assignment`, and
636 /// `no_type` otherwise.
637 template <class U>
638 static
639 yes_type match(typename U::propagate_on_container_copy_assignment *);
640 template <class U>
641 static no_type match(...);
642
643 public:
644 static const bool value =
645 sizeof(match<ALLOCATOR_TYPE>(0)) == sizeof(yes_type);
647};
648
649 // ================================
650 // AllocatorTraits_PropOnCopyAssign
651 // ================================
652
653/// This `struct` template sets the boolean type for the attribute named
654/// `propagate_on_container_copy_assignment` to `bsl::false_type` if the
655/// given (template parameter) `ALLOCATOR_TYPE` does not define such an
656/// alias (i.e.,
657/// `false == AllocatorTraits_HasPropOnCopyAssign<ALLOCATOR_TYPE>::value`).
658template <class ALLOCATOR_TYPE,
663
664/// This `struct` template sets the boolean type for the attribute named
665/// `propagate_on_container_copy_assignment` to the nested type alias in the
666/// given (template parameter) `ALLOCATOR_TYPE` if `ALLOCATOR_TYPE` defines
667/// such an alias (i.e.,
668/// `true == AllocatorTraits_HasPropOnCopyAssign<ALLOCATOR_TYPE>::value`).
669template <class ALLOC>
671 : public ALLOC::propagate_on_container_copy_assignment
672{
673};
674
675 // ===================================
676 // AllocatorTraits_HasPropOnMoveAssign
677 // ===================================
678
679/// This `struct` template provides a mechanism for determining whether a
680/// given (template parameter) `ALLOCATOR_TYPE` defines a nested alias named
681///`propagate_on_container_move_assignment`. The static boolean member
682/// `value` (nested alias named `type`) is `true` (`bsl::true_type`) if
683/// `ALLOCATOR_TYPE` defines such an alias, and `false` (`bsl::false_type`)
684/// otherwise.
685template <class ALLOC>
687
688 private:
689 typedef struct { char a; } yes_type;
690 typedef struct { char a[2]; } no_type;
691
692 /// Return @ref yes_type if the (template parameter) `TYPE` defines a
693 /// nested alias named `propagate_on_container_move_assignment`, and
694 /// `no_type` otherwise.
695 template <class U>
696 static
697 yes_type match(typename U::propagate_on_container_move_assignment *);
698 template <class U>
699 static no_type match(...);
700
701 public:
702 static const bool value = sizeof(match<ALLOC>(0)) == sizeof(yes_type);
704};
705
706 // ================================
707 // AllocatorTraits_PropOnMoveAssign
708 // ================================
709
710/// This `struct` template sets the boolean type for the attribute named
711/// `propagate_on_container_move_assignment` to `bsl::false_type` if the
712/// given (template parameter) `ALLOCATOR_TYPE` does not define such an
713/// alias (i.e.,
714/// `false == AllocatorTraits_HasPropOnMoveAssign<ALLOCATOR_TYPE>::value`).
715template <class ALLOC,
720
721/// This `struct` template sets the boolean type for the attribute named
722/// `propagate_on_container_move_assignment` to the nested type alias in the
723/// given (template parameter) `ALLOCATOR_TYPE` if `ALLOCATOR_TYPE` defines
724/// such an alias (i.e.,
725/// `true == AllocatorTraits_HasPropOnMoveAssign<ALLOCATOR_TYPE>::value`).
726template <class ALLOC>
728 : public ALLOC::propagate_on_container_move_assignment
729{
730};
731
732 // =============================
733 // AllocatorTraits_HasPropOnSwap
734 // =============================
735
736/// This `struct` template provides a mechanism for determining whether a
737/// given (template parameter) `ALLOCATOR_TYPE` defines a nested alias named
738///`propagate_on_container_swap`. The static boolean member `value` (nested
739/// alias named `type`) is `true` (`bsl::true_type`) if `ALLOCATOR_TYPE`
740/// defines such an alias, and `false` (`bsl::false_type`) otherwise.
741template <class ALLOC>
743
744 private:
745 typedef struct { char a; } yes_type;
746 typedef struct { char a[2]; } no_type;
747
748 /// Return @ref yes_type if the (template parameter) `TYPE` defines a
749 /// nested alias named `propagate_on_container_swap`, and `no_type`
750 /// otherwise.
751 template <class U>
752 static
753 yes_type match(typename U::propagate_on_container_swap *);
754 template <class U>
755 static no_type match(...);
756
757 public:
758 static const bool value = sizeof(match<ALLOC>(0)) == sizeof(yes_type);
760};
761
762 // ==========================
763 // AllocatorTraits_PropOnSwap
764 // ==========================
765
766/// This `struct` template sets the boolean type for the attribute named
767/// `propagate_on_container_swap` to `bsl::false_type` if the given
768/// (template parameter) `ALLOCATOR_TYPE` does not define such an alias
769/// (i.e., `false == AllocatorTraits_HasPropOnSwap<ALLOCATOR_TYPE>::value`).
770template <class ALLOC, bool = AllocatorTraits_HasPropOnSwap<ALLOC>::value>
774
775/// This `struct` template sets the boolean type for the attribute named
776/// `propagate_on_container_swap` to the nested type alias in the given
777/// (template parameter) `ALLOCATOR_TYPE` if `ALLOCATOR_TYPE` defines such
778/// an alias (i.e.,
779/// `false == AllocatorTraits_HasPropOnSwap<ALLOCATOR_TYPE>::value`).
780template <class ALLOC>
781struct AllocatorTraits_PropOnSwap<ALLOC, true>
782 : public ALLOC::propagate_on_container_swap
783{
784};
785
786#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE) && \
787 defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) && \
788 defined(BSLS_COMPILERFEATURES_SUPPORT_VARIADIC_TEMPLATES)
789
790 // ==================================
791 // AllocatorTraits_HasConstructMethod
792 // ==================================
793
794template <class T, class Return, class... Args>
795struct AllocatorTraits_HasConstructMethod {
796 private:
797 template <class U>
798 static auto match(U *) ->
800 bslmf::Util::declval<Args>()...)),
801 Return>::type;
802 template <class>
803 static bsl::false_type match(...);
804
805 public:
806 typedef decltype(match<T>(0)) type;
807 static const bool value = type::value;
808};
809
810 // ================================
811 // AllocatorTraits_HasDestroyMethod
812 // ================================
813
814template <class T, class Return, class... Args>
815struct AllocatorTraits_HasDestroyMethod {
816 private:
817 template <class U>
818 static auto match(U *) ->
820 bslmf::Util::declval<Args>()...)),
821 Return>::type;
822 template <class>
823 static bsl::false_type match(...);
824
825 public:
826 typedef decltype(match<T>(0)) type;
827 static const bool value = type::value;
828};
829
830#endif
831
832 // ===========================
833 // AllocatorTraits_PointerType
834 // ===========================
835
836template <class T, class = void>
838 typedef typename T::value_type *type;
839};
840
841
842template <class T>
843struct AllocatorTraits_PointerType<T, BSLMF_VOIDTYPE(typename T::pointer)> {
844 typedef typename T::pointer type;
845};
846
847 // ================================
848 // AllocatorTraits_ConstPointerType
849 // ================================
850
851template <class T, class = void>
853 /// should be pointer_traits::rebind of template above
854 typedef const typename T::value_type *type;
855};
856
857
858template <class T>
860 T,
861 BSLMF_VOIDTYPE(typename T::const_pointer)> {
862 typedef typename T::const_pointer type;
863};
864
865
866 // ===============================
867 // AllocatorTraits_VoidPointerType
868 // ===============================
869
870template <class T, class = void>
872 /// should be pointer_traits::rebind of template above
873 typedef void *type;
874};
875
876
877template <class T>
879 T,
880 BSLMF_VOIDTYPE(typename T::void_pointer)> {
881 typedef typename T::void_pointer type;
882};
883
884 // ====================================
885 // AllocatorTraits_ConstVoidPointerType
886 // ====================================
887
888template <class T, class = void>
890 /// should be pointer_traits::rebind of template above
891 typedef const void *type;
892};
893
894
895template <class T>
897 T,
898 BSLMF_VOIDTYPE(typename T::const_void_pointer)> {
899 typedef typename T::const_void_pointer type;
900};
901
902 // ========================
903 // AllocatorTraits_SizeType
904 // ========================
905
906template <class T, class = void>
908 typedef std::size_t type;
909};
910
911
912template <class T>
913struct AllocatorTraits_SizeType<T, BSLMF_VOIDTYPE(typename T::size_type)> {
914 typedef typename T::size_type type;
915};
916
917 // ==============================
918 // AllocatorTraits_DifferenceType
919 // ==============================
920
921/// should be pointer_traits::rebind of template above
922template <class T, class = void>
924 typedef std::ptrdiff_t type;
925
926};
927
928
929template <class T>
931 T,
932 BSLMF_VOIDTYPE(typename T::difference_type)> {
933 typedef typename T::difference_type type;
934};
935
936 // ===========================
937 // AllocatorTraits_RebindFront
938 // ===========================
939
940#if defined(BSLS_COMPILERFEATURES_SUPPORT_VARIADIC_TEMPLATES)
941/// There shall be no member named `type` unless T is a class template with
942/// only type parameters.
943template <class T, class U>
945};
946
947template <template <class, class...> class ALLOC,
948 class T,
949 class ...ARGS,
950 class U>
951struct AllocatorTraits_RebindFront<ALLOC<T, ARGS...>, U> {
952 using type = ALLOC<U, ARGS...>;
953};
954#else
955template <class T, class U>
957 // There shall be no member named 'type' unless T is a class template with
958 // only type parameters.
959};
960
961template <template <class> class ALLOC,
962 class T,
963 class U>
964struct AllocatorTraits_RebindFront<ALLOC<T>, U> {
965 typedef ALLOC<U> type;
966};
967#endif
968
969 // ===========================
970 // AllocatorTraits_RebindAlloc
971 // ===========================
972
973/// should be pointer_traits::rebind of template above
974template <class T, class U, class = void>
979
980template <class T, class U>
982 T,
983 U,
984 BSLMF_VOIDTYPE(typename T::template rebind<U>::other)> {
985 typedef typename T::template rebind<U>::other type;
986};
987
988 // ===========================
989 // AllocatorTraits_CallMaxSize
990 // ===========================
991
992#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)
993template <class T, class = void>
994struct AllocatorTraits_CallMaxSize {
995
996 // PUBLIC TYPES
997 typedef typename AllocatorTraits_SizeType<T>::type SizeType;
998
999 // PUBLIC CLASS METHODS
1000
1001 /// Return the maximum size of the specified (template) parameter `T`.
1002 /// Also note that this method is defined inline to work around a
1003 /// Windows compiler bug with SFINAE functions.
1004 static SizeType max_size(const T &)
1005 {
1006 return std::numeric_limits<SizeType>::max() /
1007 sizeof(typename T::value_type);
1008 }
1009};
1010
1011// Due to the dependence on expression SFINAE to detect the presence of a
1012// @ref max_size member of the allocator, this is only done on more modern
1013// platforms.
1014template <class T>
1015struct AllocatorTraits_CallMaxSize<
1016 T,
1017 BSLMF_VOIDTYPE(decltype(bslmf::Util::declval<T>().max_size()))> {
1018
1019 // PUBLIC TYPES
1020 typedef typename AllocatorTraits_SizeType<T>::type SizeType;
1021
1022 // PUBLIC CLASS METHODS
1023
1024 /// Return the maximum size of the specified `alloc`. Also note that
1025 /// this method is defined inline to work around a Windows compiler bug
1026 /// with SFINAE functions.
1027 static SizeType max_size(const T &alloc)
1028 {
1029 return alloc.max_size();
1030 }
1031};
1032#endif
1033
1034} // close namespace bslma
1035
1036
1037namespace bsl {
1038
1039 // ======================
1040 // class allocator_traits
1041 // ======================
1042
1043/// This class supports the complete interface of the C++11
1044/// `allocator_traits` class template, which provides a uniform mechanism
1045/// for accessing nested types within, and operations on, any
1046/// standard-conforming allocator. A specialization of this class template
1047/// for `bsl::allocator` provides support for Bloomberg's `bslma` allocator
1048/// model (see the @ref bslma_bslallocator component for more details). In
1049/// C++11 compilation environments, the `construct` methods forward to the
1050/// allocator's `construct` method if such a method matching the (variable
1051/// number of) specified constructor arguments exists; otherwise, the
1052/// `construct` method falls back to invoking the constructor of the element
1053/// type directly. In C++03 compilation environments, there is no reliable
1054/// way to detect if the type provide a method that matches a (variable
1055/// number of) specified arguments; therefore, we require that standard
1056/// allocator types define `construct` methods taking a variable number of
1057/// arguments in those environments. This implementation is not
1058/// fully-standard-conforming in that it does not support deduce data types
1059/// that are not specified in the allocator.
1060template <class ALLOCATOR_TYPE>
1062
1063 private:
1064
1065 typedef typename BloombergLP::bslma::AllocatorTraits_HasSelectOnCopyMethod<
1066 ALLOCATOR_TYPE>::type DelegateSelectMethod;
1067
1068 /// Return the result of invoking the
1069 /// `select_on_container_copy_construction` method on the specified
1070 /// `stdAllocator`.
1071 static
1072 ALLOCATOR_TYPE selectOnCopyConstruct(const ALLOCATOR_TYPE& stdAllocator,
1073 true_type);
1074
1075 /// Return the specified `stdAllocator`. Note that this behavior
1076 /// enforces a default policy of propagating the allocator on copy
1077 /// construction when using a standard allocator.
1078 static
1079 ALLOCATOR_TYPE selectOnCopyConstruct(const ALLOCATOR_TYPE& stdAllocator,
1080 false_type);
1081
1082#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE) && \
1083 defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) && \
1084 defined(BSLS_COMPILERFEATURES_SUPPORT_VARIADIC_TEMPLATES)
1085 /// Construct an object of (template parameter) type `ELEMENT_TYPE` at
1086 /// the specified `elementAddr`, either by 1) calling the `construct`
1087 /// method on `basicAllocator` with `elemAddr` and the specified
1088 /// (variable number of) `arguments` if the (template parameter) type
1089 /// `ALLOCATOR_TYPE` defines such a method, or 2) forwarding the
1090 /// specified (variable number of) `arguments` to the constructor of
1091 /// `ELEMENT_TYPE` directly (and ignoring `basicAllocator`) otherwise.
1092 /// The behavior is undefined unless `elementAddr` refers to valid,
1093 /// uninitialized storage.
1094 template <class ELEMENT_TYPE, class... Args>
1095 static typename bsl::enable_if<
1096 BloombergLP::bslma::AllocatorTraits_HasConstructMethod<ALLOCATOR_TYPE,
1097 void,
1098 ELEMENT_TYPE *,
1099 Args...>::value,
1100 void>::type
1101 privateConstruct(ALLOCATOR_TYPE& basicAllocator,
1102 ELEMENT_TYPE *elementAddr,
1103 Args&&... arguments);
1104 template <class ELEMENT_TYPE, class... Args>
1105 static typename bsl::enable_if<
1106 !BloombergLP::bslma::AllocatorTraits_HasConstructMethod<
1107 ALLOCATOR_TYPE,
1108 void,
1109 ELEMENT_TYPE *,
1110 Args...>::value,
1111 void>::type
1112 privateConstruct(ALLOCATOR_TYPE& basicAllocator,
1113 ELEMENT_TYPE *elementAddr,
1114 Args&&... arguments);
1115
1116 template <class ELEMENT_TYPE>
1117 static typename bsl::enable_if<
1118 BloombergLP::bslma::AllocatorTraits_HasDestroyMethod<
1119 ALLOCATOR_TYPE,
1120 void,
1121 ELEMENT_TYPE *>::value,
1122 void>::type
1123 privateDestroy(ALLOCATOR_TYPE& basicAllocator, ELEMENT_TYPE *elementAddr);
1124
1125 /// Destroy the object of (template parameter) type `ELEMENT_TYPE` at
1126 /// the specified `elementAddr`, either by 1) calling the `destroy`
1127 /// method on `basicAllocator` with `elemAddr` as the sole argument if
1128 /// the (template parameter) type `ALLOCATOR_TYPE` defines such a
1129 /// method, or 2) calling the destructor directly on `elementAddr` (and
1130 /// ignoring `basicAllocator`) otherwise. The behavior is undefined
1131 /// unless `elementAddr` refers to a valid, constructed object.
1132 template <class ELEMENT_TYPE>
1133 static typename bsl::enable_if<
1134 !BloombergLP::bslma::AllocatorTraits_HasDestroyMethod<
1135 ALLOCATOR_TYPE,
1136 void,
1137 ELEMENT_TYPE *>::value,
1138 void>::type
1139 privateDestroy(ALLOCATOR_TYPE& basicAllocator, ELEMENT_TYPE *elementAddr);
1140#endif
1141
1142 public:
1143 // PUBLIC TYPES
1144 typedef ALLOCATOR_TYPE allocator_type;
1145 typedef typename ALLOCATOR_TYPE::value_type value_type;
1146
1147 typedef typename
1148 BloombergLP::bslma::AllocatorTraits_PointerType<ALLOCATOR_TYPE>::type
1150 typedef typename
1151 BloombergLP::bslma::AllocatorTraits_ConstPointerType<ALLOCATOR_TYPE>::type
1153 typedef typename
1154 BloombergLP::bslma::AllocatorTraits_VoidPointerType<ALLOCATOR_TYPE>::type
1156 typedef typename BloombergLP::bslma::
1157 AllocatorTraits_ConstVoidPointerType<ALLOCATOR_TYPE>::type
1159
1160 typedef typename
1161 BloombergLP::bslma::AllocatorTraits_DifferenceType<ALLOCATOR_TYPE>::type
1163 typedef typename
1164 BloombergLP::bslma::AllocatorTraits_SizeType<ALLOCATOR_TYPE>::type
1166
1167#ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
1168 template <class ELEMENT_TYPE>
1169 using rebind_alloc = typename
1170 BloombergLP::bslma::AllocatorTraits_RebindAlloc<ALLOCATOR_TYPE,
1171 ELEMENT_TYPE>::type;
1172
1173 template <class ELEMENT_TYPE>
1175#else // !BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
1176 template <class ELEMENT_TYPE>
1178 : BloombergLP::bslma::AllocatorTraits_RebindAlloc<ALLOCATOR_TYPE,
1179 ELEMENT_TYPE>::type
1180 {
1181 // Note that this class attempts to emulate an alias template, but is
1182 // not complete. In general, code that must support C++03 should use
1183 // 'rebind_traits<ELEMENT_TYPE>::allocator_type' instead of
1184 // 'rebind_alloc<ELEMENT_TYPE>' because that nested typedef is the
1185 // preferred actual allocator type and not a subclass of the desired
1186 // type.
1187
1188 typedef typename BloombergLP::bslma::
1189 AllocatorTraits_RebindAlloc<ALLOCATOR_TYPE, ELEMENT_TYPE>::type
1191
1192 template <typename ARG>
1193 rebind_alloc(const ARG& allocatorArg)
1194 // Convert from anything that can be used to cosntruct the base
1195 // type. This might be better if SFINAE-ed out using
1196 // 'is_convertible', but stressing older compilers more seems
1197 // unwise.
1198 : allocator_type(allocatorArg)
1199 {
1200 }
1201 };
1202
1203 template <class ELEMENT_TYPE>
1204 struct rebind_traits : allocator_traits<typename allocator_traits::template
1205 rebind_alloc<ELEMENT_TYPE>::allocator_type>
1206 {
1207 };
1208#endif // !BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
1209
1210 // Allocation functions
1211
1212 /// Return `basicAllocator.allocate(n)`.
1213 static pointer allocate(ALLOCATOR_TYPE& basicAllocator, size_type n);
1214
1215 /// Return `basicAllocator.allocate(n, hint)`.
1216 static pointer allocate(ALLOCATOR_TYPE& basicAllocator,
1217 size_type n,
1218 const_void_pointer hint);
1219
1220 /// Invoke `basicAllocator.deallocate(elementAddr, n)`. The behavior is
1221 /// undefined unless the specified `elementAddr` was returned from a
1222 /// prior call to the `allocate` method of an allocator that compares
1223 /// equal to the specified `allocator`, and has not yet been passed to a
1224 /// `deallocate` call of such an allocator object.
1225 static void deallocate(ALLOCATOR_TYPE& basicAllocator,
1226 pointer elementAddr,
1227 size_type n);
1228
1229 // Element creation functions
1230
1231#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=14
1232
1233 /// Construct an object of (template parameter) type `ELEMENT_TYPE` at
1234 /// the specified `elementAddr`, either by 1) calling the `construct`
1235 /// method on `basicAllocator` with `elemAddr` and the specified
1236 /// (variable number of) `arguments` if the (template parameter) type
1237 /// `ALLOCATOR_TYPE` defines such a method, or 2) forwarding the
1238 /// specified (variable number of) `arguments` to the constructor of
1239 /// `ELEMENT_TYPE` directly (and ignoring `basicAllocator`) otherwise.
1240 /// The behavior is undefined unless `elementAddr` refers to valid,
1241 /// uninitialized storage.
1242 template <class ELEMENT_TYPE, class... Args>
1243 static void construct(ALLOCATOR_TYPE& basicAllocator,
1244 ELEMENT_TYPE *elementAddr,
1245 Args&&... arguments);
1246#endif
1247
1248 /// Destroy the object of (template parameter) type `ELEMENT_TYPE` at
1249 /// the specified `elementAddr`, either by 1) calling the `destroy`
1250 /// method on `basicAllocator` with `elemAddr` as the sole argument if
1251 /// the (template parameter) type `ALLOCATOR_TYPE` defines such a
1252 /// method, or 2) calling the destructor directly on `elementAddr` (and
1253 /// ignoring `basicAllocator`) otherwise. The behavior is undefined
1254 /// unless `elementAddr` refers to a valid, constructed object.
1255 template <class ELEMENT_TYPE>
1256 static void destroy(ALLOCATOR_TYPE& basicAllocator,
1257 ELEMENT_TYPE *elementAddr);
1258
1259 /// Return the largest number of `value_type` objects that could
1260 /// reasonably be returned by a single invocation of `allocate` for the
1261 /// specified `allocator`, i.e., `allocator.max_size()`.
1262 static size_type max_size(const ALLOCATOR_TYPE& basicAllocator)
1264
1265 // Allocator propagation traits
1266
1267 /// Return a copy of the allocator that should be used to copy-
1268 /// construct one container from another container whose allocator is
1269 /// the specified `rhs`. If the parameterized `ALLOCATOR_TYPE` defines
1270 /// a method `select_on_container_copy_construction`, this function
1271 /// returns the result of calling that method on `rhs`; otherwise, this
1272 /// method enforces the default policy of propagating the allocator on
1273 /// copy construction, as is standard practice for standard allocators
1274 /// (i.e., returns `rhs`). Note that the specialization of this class
1275 /// template for `bsl::allocator` (in the @ref bslma_bslallocator
1276 /// component) provides the alternate default behavior of *not*
1277 /// propagating the allocator on copy construction (i.e., returning a
1278 /// default-constructed allocator object).
1279 static ALLOCATOR_TYPE
1280 select_on_container_copy_construction(const ALLOCATOR_TYPE& rhs);
1281
1282 /// Identical to, or derived from `true_type` if two allocators of
1283 /// parameterized `ALLOCATOR_TYPE` always compare equal; otherwise
1284 /// identical to or derived from `false_type`. This type is
1285 /// `ALLOCATOR_TYPE::is_always_equal` if such a type is defined, and
1286 /// `is_empty<ALLOCATOR_TYPE>` otherwise.
1287 typedef typename BloombergLP::bslma::AllocatorTraits_IsAlwaysEqual<
1288 ALLOCATOR_TYPE>::type is_always_equal;
1289
1290 /// Identical to, or derived from `true_type` if an allocator of
1291 /// parameterized `ALLOCATOR_TYPE` should be copied when a container
1292 /// using that `ALLOCATOR_TYPE` is copy-assigned; otherwise identical to
1293 /// or derived from `false_type`. This type is
1294 /// `ALLOCATOR_TYPE::propagate_on_container_copy_assignment` if such a
1295 /// type is defined, and `false_type` otherwise.
1296 typedef typename BloombergLP::bslma::AllocatorTraits_PropOnCopyAssign<
1298
1299 /// Identical to, or derived from `true_type` if an allocator of
1300 /// parameterized `ALLOCATOR_TYPE` should be moved when a container
1301 /// using that `ALLOCATOR_TYPE` is move-assigned; otherwise identical to
1302 /// or derived from `false_type`. This type is
1303 /// `ALLOCATOR_TYPE::propagate_on_container_move_assignment` if such a
1304 /// type is defined, and `false_type` otherwise.
1305 typedef typename BloombergLP::bslma::AllocatorTraits_PropOnMoveAssign<
1307
1308 /// Identical to, or derived from `true_type` if the allocators of
1309 /// parameterized `ALLOCATOR_TYPE` should be swapped when containers
1310 /// using that `ALLOCATOR_TYPE` are swapped; otherwise identical to or
1311 /// derived from `false_type`. This type is
1312 /// `ALLOCATOR_TYPE::propagate_on_container_swap` if such a type is
1313 /// defined, and `false_type` otherwise.
1314 typedef typename BloombergLP::bslma::AllocatorTraits_PropOnSwap<
1315 ALLOCATOR_TYPE>::type propagate_on_container_swap;
1316};
1317
1318 // ========================================
1319 // class allocator_traits<ALLOCATOR_TYPE *>
1320 // ========================================
1321
1322/// TBD: improve comment This is an empty class specialization of
1323/// `allocator_traits` for pointer types that (intentionally) does not
1324/// define any of the traits typedefs. It's needed in order make
1325/// unambiguous function overloads that take both a standard allocator by
1326/// value and a `bslma::Allocator *`. By using the typedefs defined in
1327/// `allocator_traits` in the signature of functions taking standard
1328/// allocators, we can ensure that those overloads are not considered when
1329/// using `bslma`-style allocators.
1330template <class ALLOCATOR_TYPE>
1331struct allocator_traits<ALLOCATOR_TYPE *> {
1332};
1333
1334} // close namespace bsl
1335
1336// ============================================================================
1337// INLINE AND TEMPLATE STATIC MEMBER FUNCTION DEFINITIONS
1338// ============================================================================
1339
1340
1341namespace bsl {
1342
1343 // ----------------------
1344 // class allocator_traits
1345 // ----------------------
1346
1347
1348template <class ALLOCATOR_TYPE>
1349inline
1350ALLOCATOR_TYPE allocator_traits<ALLOCATOR_TYPE>::selectOnCopyConstruct(
1351 const ALLOCATOR_TYPE& stdAllocator,
1352 true_type)
1353{
1354 return stdAllocator.select_on_container_copy_construction();
1355}
1356
1357template <class ALLOCATOR_TYPE>
1358inline
1359ALLOCATOR_TYPE allocator_traits<ALLOCATOR_TYPE>::selectOnCopyConstruct(
1360 const ALLOCATOR_TYPE& stdAllocator,
1361 false_type)
1362{
1363 return stdAllocator;
1364}
1365
1366#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE) && \
1367 defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) && \
1368 defined(BSLS_COMPILERFEATURES_SUPPORT_VARIADIC_TEMPLATES)
1369template <class ALLOCATOR_TYPE>
1370template <class ELEMENT_TYPE, class... Args>
1371inline
1372typename bsl::enable_if<
1373 BloombergLP::bslma::AllocatorTraits_HasConstructMethod<ALLOCATOR_TYPE,
1374 void,
1375 ELEMENT_TYPE *,
1376 Args...>::value,
1377 void>::type
1378allocator_traits<ALLOCATOR_TYPE>::privateConstruct(
1379 ALLOCATOR_TYPE& basicAllocator,
1380 ELEMENT_TYPE *elementAddr,
1381 Args&&... arguments)
1382{
1383 basicAllocator.construct(
1384 elementAddr, BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
1385}
1386
1387template <class ALLOCATOR_TYPE>
1388template <class ELEMENT_TYPE, class... Args>
1389inline
1390typename bsl::enable_if<
1391 !BloombergLP::bslma::AllocatorTraits_HasConstructMethod<ALLOCATOR_TYPE,
1392 void,
1393 ELEMENT_TYPE *,
1394 Args...>::value,
1395 void>::type
1396allocator_traits<ALLOCATOR_TYPE>::privateConstruct(ALLOCATOR_TYPE&,
1397 ELEMENT_TYPE *elementAddr,
1398 Args&&... arguments)
1399{
1400 ::new (static_cast<void *>(elementAddr))
1401 ELEMENT_TYPE(BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
1402}
1403
1404template <class ALLOCATOR_TYPE>
1405template <class ELEMENT_TYPE>
1406inline
1407typename bsl::enable_if<BloombergLP::bslma::AllocatorTraits_HasDestroyMethod<
1408 ALLOCATOR_TYPE,
1409 void,
1410 ELEMENT_TYPE *>::value,
1411 void>::type
1412allocator_traits<ALLOCATOR_TYPE>::privateDestroy(
1413 ALLOCATOR_TYPE& basicAllocator,
1414 ELEMENT_TYPE *elementAddr)
1415{
1416 basicAllocator.destroy(elementAddr);
1417}
1418
1419template <class ALLOCATOR_TYPE>
1420template <class ELEMENT_TYPE>
1421inline
1422typename bsl::enable_if<!BloombergLP::bslma::AllocatorTraits_HasDestroyMethod<
1423 ALLOCATOR_TYPE,
1424 void,
1425 ELEMENT_TYPE *>::value,
1426 void>::type
1427allocator_traits<ALLOCATOR_TYPE>::privateDestroy(ALLOCATOR_TYPE&,
1428 ELEMENT_TYPE *elementAddr)
1429{
1430 elementAddr->~ELEMENT_TYPE();
1431}
1432#endif
1433
1434// Allocation functions
1435
1436template <class ALLOCATOR_TYPE>
1437inline
1439allocator_traits<ALLOCATOR_TYPE>::allocate(ALLOCATOR_TYPE& basicAllocator,
1440 size_type n)
1441{
1442 return basicAllocator.allocate(n);
1443}
1444
1445template <class ALLOCATOR_TYPE>
1446inline
1448allocator_traits<ALLOCATOR_TYPE>::allocate(ALLOCATOR_TYPE& basicAllocator,
1449 size_type n,
1450 const_void_pointer hint)
1451{
1452 return basicAllocator.allocate(n, hint);
1453}
1454
1455template <class ALLOCATOR_TYPE>
1456inline
1457void
1459 pointer elementAddr,
1460 size_type n)
1461{
1462 basicAllocator.deallocate(elementAddr, n);
1463}
1464
1465// ELEMENT CREATION FUNCTIONS
1466
1467#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1468template <class ALLOCATOR_TYPE>
1469template <class ELEMENT_TYPE, class... Args>
1470inline
1471void
1472allocator_traits<ALLOCATOR_TYPE>::construct(ALLOCATOR_TYPE& basicAllocator,
1473 ELEMENT_TYPE *elementAddr,
1474 Args&&... arguments)
1475{
1476#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)
1477 privateConstruct(basicAllocator,
1478 elementAddr,
1479 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
1480#else
1481 // Cannot sniff out whether 'basicAllocator.construct(...)' is valid in
1482 // C++03, but allocators are required to have a 'construct' method, so just
1483 // call it.
1484 basicAllocator.construct(
1485 elementAddr, BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
1486#endif
1487}
1488#endif
1489
1490template <class ALLOCATOR_TYPE>
1491template <class ELEMENT_TYPE>
1492inline
1493void
1495 ELEMENT_TYPE *elementAddr)
1496{
1497// For full C++11 compatibility, this should check for the well-formedness of
1498// the allocator-specific code that is commented out below (via some SFINAE
1499// trickery), and switch to the 'DestructionUtil' implementation only if the
1500// 'destroy' member function is not available.
1501
1502// allocator.destroy(elementAddr);
1503#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE) && \
1504 defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
1505 privateDestroy(stdAllocator, elementAddr);
1506#else
1507 elementAddr->~ELEMENT_TYPE();
1508 (void) stdAllocator;
1509#endif
1510}
1511
1512template <class ALLOCATOR_TYPE>
1513inline
1516 const ALLOCATOR_TYPE& basicAllocator) BSLS_KEYWORD_NOEXCEPT
1517{
1518#if defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)
1519 return BloombergLP::bslma::
1520 AllocatorTraits_CallMaxSize<ALLOCATOR_TYPE>::max_size(basicAllocator);
1521#else
1522 // Cannot sniff out whether 'basicAllocator.max_size()' is valid in C++03,
1523 // but for now require that allocators have a @ref max_size method and just
1524 // call it.
1525 return basicAllocator.max_size();
1526#endif
1527}
1528
1529template <class ALLOCATOR_TYPE>
1530inline
1531ALLOCATOR_TYPE
1533 const ALLOCATOR_TYPE& rhs)
1534{
1535 return selectOnCopyConstruct(rhs, DelegateSelectMethod());
1536}
1537
1538} // close namespace bsl
1539
1540#endif // End C++11 code
1541
1542#endif // ! defined(INCLUDED_BSLMA_ALLOCATORTRAITS)
1543
1544// ----------------------------------------------------------------------------
1545// Copyright 2013 Bloomberg Finance L.P.
1546//
1547// Licensed under the Apache License, Version 2.0 (the "License");
1548// you may not use this file except in compliance with the License.
1549// You may obtain a copy of the License at
1550//
1551// http://www.apache.org/licenses/LICENSE-2.0
1552//
1553// Unless required by applicable law or agreed to in writing, software
1554// distributed under the License is distributed on an "AS IS" BASIS,
1555// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1556// See the License for the specific language governing permissions and
1557// limitations under the License.
1558// ----------------------------- END-OF-FILE ----------------------------------
1559
1560/** @} */
1561/** @} */
1562/** @} */
#define BSLMF_VOIDTYPE(ARG)
Definition bslmf_voidtype.h:335
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2018
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
Definition bdlb_printmethods.h:283
integral_constant< bool, false > false_type
Definition bslmf_integralconstant.h:297
integral_constant< bool, true > true_type
Definition bslmf_integralconstant.h:303
Definition balxml_encoderoptions.h:68
Definition bdlbb_blob.h:576
Definition bslma_allocatortraits.h:1180
rebind_alloc(const ARG &allocatorArg)
Definition bslma_allocatortraits.h:1193
BloombergLP::bslma::AllocatorTraits_RebindAlloc< ALLOCATOR_TYPE, ELEMENT_TYPE >::type allocator_type
Definition bslma_allocatortraits.h:1190
Definition bslma_allocatortraits.h:1206
Definition bslma_allocatortraits.h:1061
static pointer allocate(ALLOCATOR_TYPE &basicAllocator, size_type n)
Return basicAllocator.allocate(n).
Definition bslma_allocatortraits.h:1439
BloombergLP::bslma::AllocatorTraits_ConstPointerType< ALLOCATOR_TYPE >::type const_pointer
Definition bslma_allocatortraits.h:1152
BloombergLP::bslma::AllocatorTraits_VoidPointerType< ALLOCATOR_TYPE >::type void_pointer
Definition bslma_allocatortraits.h:1155
BloombergLP::bslma::AllocatorTraits_PropOnCopyAssign< ALLOCATOR_TYPE >::type propagate_on_container_copy_assignment
Definition bslma_allocatortraits.h:1297
BloombergLP::bslma::AllocatorTraits_PropOnMoveAssign< ALLOCATOR_TYPE >::type propagate_on_container_move_assignment
Definition bslma_allocatortraits.h:1306
static ALLOCATOR_TYPE select_on_container_copy_construction(const ALLOCATOR_TYPE &rhs)
Definition bslma_allocatortraits.h:1532
BloombergLP::bslma::AllocatorTraits_SizeType< ALLOCATOR_TYPE >::type size_type
Definition bslma_allocatortraits.h:1165
static void construct(ALLOCATOR_TYPE &basicAllocator, ELEMENT_TYPE *elementAddr, Args &&... arguments)
Definition bslma_allocatortraits.h:1472
static pointer allocate(ALLOCATOR_TYPE &basicAllocator, size_type n, const_void_pointer hint)
Return basicAllocator.allocate(n, hint).
Definition bslma_allocatortraits.h:1448
static size_type max_size(const ALLOCATOR_TYPE &basicAllocator) BSLS_KEYWORD_NOEXCEPT
Definition bslma_allocatortraits.h:1515
BloombergLP::bslma::AllocatorTraits_PointerType< ALLOCATOR_TYPE >::type pointer
Definition bslma_allocatortraits.h:1149
static void destroy(ALLOCATOR_TYPE &basicAllocator, ELEMENT_TYPE *elementAddr)
Definition bslma_allocatortraits.h:1494
BloombergLP::bslma::AllocatorTraits_IsAlwaysEqual< ALLOCATOR_TYPE >::type is_always_equal
Definition bslma_allocatortraits.h:1288
static void deallocate(ALLOCATOR_TYPE &basicAllocator, pointer elementAddr, size_type n)
Definition bslma_allocatortraits.h:1458
BloombergLP::bslma::AllocatorTraits_PropOnSwap< ALLOCATOR_TYPE >::type propagate_on_container_swap
Definition bslma_allocatortraits.h:1315
ALLOCATOR_TYPE allocator_type
Definition bslma_allocatortraits.h:1144
BloombergLP::bslma::AllocatorTraits_ConstVoidPointerType< ALLOCATOR_TYPE >::type const_void_pointer
Definition bslma_allocatortraits.h:1158
BloombergLP::bslma::AllocatorTraits_DifferenceType< ALLOCATOR_TYPE >::type difference_type
Definition bslma_allocatortraits.h:1162
ALLOCATOR_TYPE::value_type value_type
Definition bslma_allocatortraits.h:1145
Definition bslmf_enableif.h:525
Definition bslmf_integralconstant.h:244
Definition bslmf_isempty.h:315
Definition bslmf_issame.h:146
Definition bslma_allocatortraits.h:852
const T::value_type * type
should be pointer_traits::rebind of template above
Definition bslma_allocatortraits.h:854
Definition bslma_allocatortraits.h:889
const void * type
should be pointer_traits::rebind of template above
Definition bslma_allocatortraits.h:891
should be pointer_traits::rebind of template above
Definition bslma_allocatortraits.h:923
std::ptrdiff_t type
Definition bslma_allocatortraits.h:924
Definition bslma_allocatortraits.h:529
static const bool value
Definition bslma_allocatortraits.h:547
bsl::integral_constant< bool, value > type
Definition bslma_allocatortraits.h:550
Definition bslma_allocatortraits.h:628
static const bool value
Definition bslma_allocatortraits.h:644
bsl::integral_constant< bool, value > type
Definition bslma_allocatortraits.h:646
Definition bslma_allocatortraits.h:686
bsl::integral_constant< bool, value > type
Definition bslma_allocatortraits.h:703
static const bool value
Definition bslma_allocatortraits.h:702
Definition bslma_allocatortraits.h:742
bsl::integral_constant< bool, value > type
Definition bslma_allocatortraits.h:759
static const bool value
Definition bslma_allocatortraits.h:758
Definition bslma_allocatortraits.h:588
bsl::integral_constant< bool, value > type
Definition bslma_allocatortraits.h:614
static const bool value
Definition bslma_allocatortraits.h:612
Definition bslma_allocatortraits.h:563
Definition bslma_allocatortraits.h:837
T::value_type * type
Definition bslma_allocatortraits.h:838
Definition bslma_allocatortraits.h:661
Definition bslma_allocatortraits.h:718
Definition bslma_allocatortraits.h:772
T::template rebind< U >::other type
Definition bslma_allocatortraits.h:985
should be pointer_traits::rebind of template above
Definition bslma_allocatortraits.h:975
AllocatorTraits_RebindFront< T, U >::type type
Definition bslma_allocatortraits.h:976
ALLOC< U > type
Definition bslma_allocatortraits.h:965
Definition bslma_allocatortraits.h:956
T::size_type type
Definition bslma_allocatortraits.h:914
Definition bslma_allocatortraits.h:907
std::size_t type
Definition bslma_allocatortraits.h:908
Definition bslma_allocatortraits.h:871
void * type
should be pointer_traits::rebind of template above
Definition bslma_allocatortraits.h:873