BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslma_polymorphicallocator.h
Go to the documentation of this file.
1/// @file bslma_polymorphicallocator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_polymorphicallocator.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_POLYMORPHICALLOCATOR
9#define INCLUDED_BSLMA_POLYMORPHICALLOCATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_polymorphicallocator bslma_polymorphicallocator
15/// @brief Provide an allocator interface for `bsl::memory_resource` objects.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_polymorphicallocator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_polymorphicallocator-purpose"> Purpose</a>
25/// * <a href="#bslma_polymorphicallocator-classes"> Classes </a>
26/// * <a href="#bslma_polymorphicallocator-description"> Description </a>
27/// * <a href="#bslma_polymorphicallocator-thread-safety"> Thread Safety </a>
28/// * <a href="#bslma_polymorphicallocator-usage"> Usage </a>
29/// * <a href="#bslma_polymorphicallocator-example-1-a-class-that-allocates-memory"> Example 1: A class that allocates memory </a>
30///
31/// # Purpose {#bslma_polymorphicallocator-purpose}
32/// Provide an allocator interface for `bsl::memory_resource` objects.
33///
34/// # Classes {#bslma_polymorphicallocator-classes}
35///
36/// - bsl::polymorphic_allocator: STL-compatible polymorphic allocator template
37///
38/// **Canonical header:** bsl_memory_resource.h
39///
40/// @see bslma_memoryresource, bslma_bslallocator
41///
42/// # Description {#bslma_polymorphicallocator-description}
43/// This component provides an STL-compatible proxy for any
44/// resource class derived from `bsl::memory_resource`. The
45/// `bsl::polymorphic_allocator` interface is identical to that of
46/// `std::pmr::polymorphic_allocator` from the C++17 Standard Library; in fact,
47/// the former type is an alias for the latter type when using a C++17 or later
48/// library supplied by the platform.
49///
50/// The proxy class, `bsl::polymorphic_allocator` is a template that adheres to
51/// the allocator requirements defined in section [allocator.requirements] of
52/// the C++ standard. `bsl::polymorphic_allocator` may be used to instantiate
53/// any class template that is parameterized by a standard allocator. The
54/// container is expected to allocate memory for its own use through the
55/// allocator. A `bsl::polymorphic_allocator` object is initialized using a
56/// pointer to a resource object derived from `bsl::memory_resource`. Different
57/// types of memory resources use different allocation mechanisms, so this
58/// approach gives the programmer run time control over how the container
59/// obtains memory.
60///
61/// A container constructs its elements by calling the `construct` method on its
62/// allocator. Importantly, `bsl::polymorphic_allocator` is a *scoped*
63/// *allocator* -- when its `construct` method is called, the allocator passes
64/// itself to the constructor of the object being constructed (if that object is
65/// allocator aware (AA) and uses a compatible the allocator type). Thus, a
66/// container instantiated with a scoped allocator ensures that its elements use
67/// the same allocator as the container itself.
68///
69/// A container using `bsl::polymorphic_allocator` should not copy its allocator
70/// on assignment and thus, to avoid errors, `bsl::polymorphic_allocator`, is
71/// not assignable. By design, a member of type `bsl::polymorphic_allocator`
72/// will prevent the client class from having a compiler-generated (defaulted)
73/// assignment operator because such an assignment operator would almost
74/// certainly do the wrong thing -- copying the allocator and allocated objects
75/// instead of cloning those objects using the destination allocator. Once
76/// constructed, there is no straightforward way to rebind a
77/// `bsl::polymorphic_allocator` to use a different resource.
78///
79/// Instantiations of `bsl::polymorphic_allocator` have reference semantics. A
80/// `bsl::polymorphic_allocator` object does not "own" the `bslma::Allocator`
81/// with which it is initialized; copying a `bsl::polymorphic_allocator` object
82/// does not copy its resource object and destroying a
83/// `bsl::polymorphic_allocator` does not destroy its resource object. Two
84/// `bsl::polymorphic_allocator` objects compare equal if and only if the
85/// resource objects they refer to compare equal.
86///
87/// ## Thread Safety {#bslma_polymorphicallocator-thread-safety}
88///
89///
90/// Because it is immutable, non-assignable, and has reference semantics, a
91/// single `bsl::polymorphic_allocator` object is safe for concurrent access by
92/// multiple threads if and only if the `bsl::memory_resource` it references is
93/// safe for concurrent access from multiple threads. Separate objects of
94/// `bsl::polymorphic_allocator` type may safely be used in separate threads if
95/// and only if the `bsl::memory_resource` objects they reference are,
96/// themselves, safe for concurrent access.
97///
98/// ## Usage {#bslma_polymorphicallocator-usage}
99///
100///
101/// This section illustrates intended use of this component.
102///
103/// ### Example 1: A class that allocates memory {#bslma_polymorphicallocator-example-1-a-class-that-allocates-memory}
104///
105///
106/// In this example, we define a class template, `Holder<TYPE>`, that holds a
107/// single instance of `TYPE` on the heap. `Holder` is designed such that its
108/// memory use can be customized by supplying an appropriate allocator. A
109/// holder object can be empty and it can be move-constructed even if
110/// `TYPE` is not movable. In addition, the footprint of a `Holder` object is
111/// the same (typically the size of 2 pointers), regardless of the size of
112/// `TYPE`.
113///
114/// First, we create a `CountingResource` class, derived from
115/// `bsl::memory_resource`, that keeps track of the number of blocks of memory
116/// that were allocated from the resource but not yet returned to the resource;
117/// see usage example 1 in @ref bslma_memoryresource .
118/// @code
119/// #include <bslmf_movableref.h>
120/// #include <bsls_assert.h>
121/// #include <bsls_keyword.h>
122/// #include <stdint.h> // 'uintptr_t'
123///
124/// class CountingResource : public bsl::memory_resource {
125///
126/// // DATA
127/// int d_blocksOutstanding;
128///
129/// CountingResource(const CountingResource&) BSLS_KEYWORD_DELETED;
130/// CountingResource& operator=(const CountingResource&)
131/// BSLS_KEYWORD_DELETED;
132///
133/// private:
134/// // PRIVATE MANIPULATORS
135/// void* do_allocate(std::size_t bytes,
136/// std::size_t alignment) BSLS_KEYWORD_OVERRIDE;
137/// void do_deallocate(void* p, std::size_t bytes,
138/// std::size_t alignment) BSLS_KEYWORD_OVERRIDE;
139///
140/// // PRIVATE ACCESSORS
141/// bool do_is_equal(const bsl::memory_resource& other) const
142/// BSLS_KEYWORD_NOEXCEPT BSLS_KEYWORD_OVERRIDE;
143///
144/// public:
145/// // CREATORS
146/// CountingResource() : d_blocksOutstanding(0) { }
147/// ~CountingResource() BSLS_KEYWORD_OVERRIDE;
148///
149/// // ACCESSORS
150/// int blocksOutstanding() const { return d_blocksOutstanding; }
151/// };
152///
153/// CountingResource::~CountingResource()
154/// {
155/// BSLS_assert(0 == d_blocksOutstanding);
156/// }
157///
158/// void *CountingResource::do_allocate(std::size_t bytes,
159/// std::size_t alignment)
160/// {
161/// void *ret = ::operator new(bytes);
162/// if (uintptr_t(ret) & (alignment - 1)) {
163/// ::operator delete(ret);
164/// BSLS_THROW(this); // Alignment failed
165/// }
166/// ++d_blocksOutstanding;
167/// return ret;
168/// }
169///
170/// void CountingResource::do_deallocate(void* p, std::size_t, std::size_t)
171/// {
172/// ::operator delete(p);
173/// --d_blocksOutstanding;
174/// }
175///
176/// bool CountingResource::do_is_equal(const bsl::memory_resource& other) const
177/// BSLS_KEYWORD_NOEXCEPT
178/// {
179/// return this == &other;
180/// }
181/// @endcode
182/// Now we define our actual `Holder` template with with data members to hold
183/// the memory allocator and a pointer to the contained object:
184/// @code
185/// template <class TYPE>
186/// class Holder {
187/// bsl::polymorphic_allocator<TYPE> d_allocator;
188/// TYPE *d_data_p;
189/// @endcode
190/// Next, we declare the constructors. Following the pattern for
191/// allocator-aware types used in BDE, the public interface contains an
192/// `allocator_type` typedef that can be passed to each constructor.:
193/// @code
194/// public:
195/// // TYPES
196/// typedef bsl::polymorphic_allocator<TYPE> allocator_type;
197///
198/// // CREATORS
199/// explicit Holder(const allocator_type& allocator = allocator_type());
200/// explicit Holder(const TYPE& value,
201/// const allocator_type& allocator = allocator_type());
202/// Holder(const Holder& other,
203/// const allocator_type& allocator = allocator_type());
204/// Holder(bslmf::MovableRef<Holder> other); // IMPLICIT
205/// Holder(bslmf::MovableRef<Holder> other,
206/// const allocator_type& allocator);
207/// ~Holder();
208/// @endcode
209/// Next, we declare the manipulators and accessors, allowing a `Holder` to be
210/// assigned and giving a client access to its value and allocator:
211/// @code
212/// // MANIPULATORS
213/// Holder& operator=(const Holder& rhs);
214/// Holder& operator=(bslmf::MovableRef<Holder> rhs);
215/// TYPE& value() { return *d_data_p; }
216///
217/// // ACCESSORS
218/// bool isEmpty() const { return 0 == d_data_p; }
219/// const TYPE& value() const { return *d_data_p; }
220/// allocator_type get_allocator() const { return d_allocator; }
221/// };
222/// @endcode
223/// Next, we'll implement the first constructor, which creates an empty object;
224/// its only job is to store the allocator:
225/// @code
226/// template <class TYPE>
227/// Holder<TYPE>::Holder(const allocator_type& allocator)
228/// : d_allocator(allocator)
229/// , d_data_p(0)
230/// {
231/// }
232/// @endcode
233/// Next, we'll implement the second constructor, which allocates memory and
234/// constructs an object in it. The `try`/`catch` block is needed to free the
235/// memory in case the constructor for `TYPE` throws and exception. An
236/// alternative implementation would use an RAII object to automatically free
237/// the memory in the case of an exception (see @ref bslma_deallocatorproctor ):
238/// @code
239/// template <class TYPE>
240/// Holder<TYPE>::Holder(const TYPE& value, const allocator_type& allocator)
241/// : d_allocator(allocator)
242/// , d_data_p(0)
243/// {
244/// d_data_p = d_allocator.allocate(1);
245/// BSLS_TRY {
246/// ::new(d_data_p) TYPE(value);
247/// }
248/// BSLS_CATCH(...) {
249/// d_allocator.deallocate(d_data_p, 1);
250/// BSLS_RETHROW;
251/// }
252/// }
253/// @endcode
254/// Next, we'll implement a destructor that deletes the value object and
255/// deallocates the allocated memory:
256/// @code
257/// template <class TYPE>
258/// Holder<TYPE>::~Holder()
259/// {
260/// if (! isEmpty()) {
261/// d_data_p->~TYPE(); // Destroy object.
262/// d_allocator.deallocate(d_data_p, 1); // Deallocate memory.
263/// }
264/// }
265/// @endcode
266/// Finally, we've implemented enough of `Holder` to demonstrate its use.
267/// Below, we pass the `CountingResource` from Example 1 to the constructors
268/// several `Holder` objects. Each non-empty `Holder` allocates one block of
269/// memory, which is reflected in the outstanding block count. Note that the
270/// address of the resource can be passed directly to the constructors because
271/// `bsl::polymorphic_allocator` is implicitly convertible from
272/// `bsl::memory_resource *`:
273/// @code
274/// int main()
275/// {
276/// CountingResource rsrc;
277///
278/// {
279/// Holder<int> h1(&rsrc); // Empty resource
280/// assert(h1.isEmpty());
281/// assert(0 == rsrc.blocksOutstanding());
282///
283/// Holder<int> h2(2, &rsrc);
284/// assert(! h2.isEmpty());
285/// assert(1 == rsrc.blocksOutstanding());
286///
287/// Holder<double> h3(3.0, &rsrc);
288/// assert(! h3.isEmpty());
289/// assert(2 == rsrc.blocksOutstanding());
290/// }
291///
292/// assert(0 == rsrc.blocksOutstanding()); // Destructors freed memory
293/// }
294/// @endcode
295/// @}
296/** @} */
297/** @} */
298
299/** @addtogroup bsl
300 * @{
301 */
302/** @addtogroup bslma
303 * @{
304 */
305/** @addtogroup bslma_polymorphicallocator
306 * @{
307 */
308
309#include <bslscm_version.h>
310
313#include <bslma_default.h>
315#include <bslma_isstdallocator.h>
316#include <bslma_memoryresource.h>
318
320#include <bslmf_typeidentity.h>
321
322#include <bsls_annotation.h>
323#include <bsls_assert.h>
326#include <bsls_keyword.h>
327#include <bsls_libraryfeatures.h>
328#include <bsls_util.h> // 'forward<T>(V)', `Util::addressOf`
329
330#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
331// Include version that can be compiled with C++03
332// Generated on Wed Aug 30 14:35:39 2023
333// Command line: sim_cpp11_features.pl bslma_polymorphicallocator.h
334# define COMPILING_BSLMA_POLYMORPHICALLOCATOR_H
336# undef COMPILING_BSLMA_POLYMORPHICALLOCATOR_H
337#else
338
339#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
340// Use `polymorphic_allocator` from native C++17 library, if available.
341
342# include <memory_resource>
343
344namespace bsl {
345
346// Import 'polymorphic_allocator' into the 'bsl' namespace.
347template <class TYPE = std::byte>
348using polymorphic_allocator = std::pmr::polymorphic_allocator<TYPE>;
349
350} // close namespace bsl
351
352// FREE FUNCTIONS
353
354// As per issue LWG 3683 (https://cplusplus.github.io/LWG/issue3683), the C++20
355// standard as published does not provide `operator==` for comparing a
356// `polymorphic_allocator` to a type convertible to `polymorphic_allocator`,
357// e.g., a `pmr::memory_resource`. The workaround below corresponds to
358// proposed resolution 2, which differs from the accepted issue resolution
359// (proposed resolution 3) because the accepted resolution requires modifying
360// the library class itself. This workaround does not depend on C++20
361// automatic generation of multiple `operator==` and `operator!=` from a single
362// declaration of `operator==`. Because `bsl::polymorphic_allocator` is an
363// alias for `std::pmr::polymorphic_allocator`, these operators must be defined
364// in namespace `std::pmr` to be found by ADL.
365
366
367
368#if defined(BSLS_PLATFORM_CMP_MSVC)
369// The MSVC compiler, up to and including version 19.33 (aka VS 2022), has a
370// bug whereby supressing argument deduction using @ref type_identity causes a
371// linker error. The `BSLMF_POLYMORPHICALLOCATOR_NODEDUCE_T` macro below
372// provides a non-deduced `polymorphic_allocator` argument that works around
373// this problem.
374//
375// Note that this workaround will not work for a type convertible to
376// `polymorphic_allocator` via a conversion operator:
377//..
378// class C { operator bsl::polymorphic_allocator<short>() const; };
379// assert(bsl::polymorphic_allocator<short>() == C()); // won`t compile
380//..
381// As this is a rare-to-nonexistant use case, we won`t bother to fix that for
382// now.
383
384struct PolymorphicAllocator_Unique
385{
386 // A unique type not used for anything else
387};
388
389#define BSLMF_POLYMORPHICALLOCATOR_NODEDUCE_T(VAL_T) \
390 std::pmr::polymorphic_allocator< \
391 BloombergLP::bslma::PolymorphicAllocator_Unique>
392
393#else // Not MSVC compiler
394
395#define BSLMF_POLYMORPHICALLOCATOR_NODEDUCE_T(VAL_T) \
396 typename bsl::type_identity<std::pmr::polymorphic_allocator<VAL_T>>::type
397
398#endif
399
400
401
402namespace std::pmr {
403
404/// Return `true` if the specified `a` and specified `b` polymorphic
405/// allocators have equal memory resources; otherwise `false`.
406template <class TYPE>
407bool operator==(const polymorphic_allocator<TYPE>& a,
408 const BSLMF_POLYMORPHICALLOCATOR_NODEDUCE_T(TYPE)& b)
410
411/// Return `true` if the specified `a` and specified `b` polymorphic
412/// allocators have equal memory resources; otherwise `false`.
413template <class TYPE>
414bool operator==(const BSLMF_POLYMORPHICALLOCATOR_NODEDUCE_T(TYPE)& a,
415 const polymorphic_allocator<TYPE>& b)
417
418/// Return `false` if the specified `a` and specified `b` polymorphic
419/// allocators have equal memory resources; otherwise `true`.
420template <class TYPE>
421bool operator!=(const polymorphic_allocator<TYPE>& a,
422 const BSLMF_POLYMORPHICALLOCATOR_NODEDUCE_T(TYPE)& b)
424
425/// Return `false` if the specified `a` and specified `b` polymorphic
426/// allocators have equal memory resources; otherwise `true`.
427template <class TYPE>
428bool operator!=(const BSLMF_POLYMORPHICALLOCATOR_NODEDUCE_T(TYPE)& a,
429 const polymorphic_allocator<TYPE>& b)
431
432} // close namespace std::pmr
433
434#else // If C++17 library is not available
435
436 // =========================================
437 // class template bsl::polymorphic_allocator
438 // =========================================
439
440namespace bsl {
441
442/// An STL-compatible proxy for any resource class derived from
443/// `bsl::memory_resource`. This class template is a pre-C++17
444/// implementation of `std::pmr::polymorphic_allocator` from the C++17
445/// Standard Library. Note that there are a number of methods (e.g.,
446/// @ref max_size ) that are not in the C++17 version of this class. These
447/// members exist for compatibility with C++03 versions of the standard
448/// library, which don't use `allocator_traits`.
449///
450/// See @ref bslma_polymorphicallocator
451template <class TYPE = unsigned char>
453
454 // DATA
455 memory_resource *d_resource;
456
457 // NOT IMPLEMENTED
460
461 public:
462 // TYPES
463 typedef std::size_t size_type;
464 typedef std::ptrdiff_t difference_type;
465 typedef TYPE *pointer;
466 typedef const TYPE *const_pointer;
467 typedef TYPE& reference;
468 typedef const TYPE& const_reference;
469 typedef TYPE value_type;
470
471 /// This nested `struct` template, parameterized by `ANY_TYPE`, provides
472 /// a namespace for an `other` type alias, which is an allocator type
473 /// following the same template as this one but that allocates elements
474 /// of `ANY_TYPE`. Note that this allocator type is convertible to and
475 /// from `other` for any type, including `void`.
476 template <class ANY_TYPE>
480
481 // CREATORS
482
483 /// Create an allocator that will forward allocation calls to the
484 /// object pointed to by `bslma::Default::defaultAllocator()`.
485 /// Postcondition:
486 /// @code
487 /// this->resource() == bslma::Default::defaultAllocator()
488 /// @endcode
489 /// Note that in this C++03 implementation, the default memory resource
490 /// is the same as `bslma::Default::defaultAllocator()`.
492
493 /// Convert a `memory_resource` pointer to a `polymorphic_allocator`
494 /// object that forwards allocation calls to the object pointed to by
495 /// the specified `r`. Postcondition:
496 /// @code
497 /// this->resource() == r
498 /// @endcode
499 /// The behavior is undefined if `r` is null.
501
502 /// Create an allocator sharing the same resource object as the
503 /// specified `original`. The newly constructed allocator will compare
504 /// equal to `original`, even though they may be instantiated on
505 /// different types. Postconditions:
506 /// @code
507 /// *this == original
508 /// this->resource() == original.resource();
509 /// @endcode
510#ifdef BSLS_COMPILERFEATURES_SUPPORT_DEFAULTED_FUNCTIONS
512 BSLS_KEYWORD_NOEXCEPT = default;
513#else
516#endif
517 template<class ANY_TYPE>
520
521 /// Destroy this object. Note that this does not delete the object
522 /// pointed to by 'resource()'.
524
525 // MANIPULATORS
526
527 /// Return a block of memory having sufficient size and alignment to
528 /// hold the specified `n` objects of `value_type`, allocated from the
529 /// memory resource held by this allocator.
531
532#ifndef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
533 /// Return a block of memory having sufficient size and alignment to
534 /// hold the specified `n` objects of `value_type`, allocated from the
535 /// memory resource held by this allocator, ignoring the specified
536 /// `hint`, which is used by other allocators as a locality hint. Note
537 /// that this overload is not part of C++17
538 /// `std::pmr::polymorphic_allocator` but it is a requirement for all
539 /// C++03 allocators.
540 BSLS_ANNOTATION_NODISCARD TYPE *allocate(std::size_t n, const void *hint);
541#endif
542
543 /// Deallocate a block of memory having sufficient size and alignment to
544 /// hold the specified `n` objects of `value_type` by returning it to
545 /// the memory resource held by this allocator. The behavior is
546 /// undefined unless `p` is the address of a block previously allocated
547 /// by a call to `allocate` with the same `n` and not yet deallocated.
548 void deallocate(TYPE *p, std::size_t n);
549
550 /// Create a default-constructed object of (template parameter)
551 /// `ELEMENT_TYPE` at the specified `address`. If `ELEMENT_TYPE`
552 /// supports `bslma`-style allocation, this allocator passes itself to
553 /// the extended default constructor. If the constructor throws, the
554 /// memory at `address` is left in an unspecified state. The behavior
555 /// is undefined unless `address` refers to a block of memory having
556 /// sufficient size and alignment for an object of `ELEMENT_TYPE`.
557 template <class ELEMENT_TYPE>
558 void construct(ELEMENT_TYPE *address);
559
560 /// Create an object of (template parameter) `ELEMENT_TYPE` at the
561 /// specified `address`, constructed by forwarding the specified
562 /// `argument1` and the (variable number of) additional specified
563 /// `arguments` to the corresponding constructor of `ELEMENT_TYPE`. If
564 /// `ELEMENT_TYPE` supports `bslma`-style allocation, this allocator
565 /// passes itself to the constructor. If the constructor throws, the
566 /// memory at `address` is left in an unspecified state. Note that, in
567 /// C++03, perfect forwarding is limited such that any lvalue reference
568 /// in the `arguments` parameter pack is const-qualified when forwarded
569 /// to the `ELEMENT_TYPE` constructor; only `argument1` can be forwarded
570 /// as an unqualified lvalue. The behavior is undefined unless
571 /// `address` refers to a block of memory having sufficient size and
572 /// alignment for an object of `ELEMENT_TYPE`.
573#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=14
574 template <class ELEMENT_TYPE, class ARG1, class... ARGS>
575 void construct(ELEMENT_TYPE *address,
576 ARG1& argument1,
577 ARGS&&... arguments);
578 template <class ELEMENT_TYPE, class ARG1, class... ARGS>
579 void construct(ELEMENT_TYPE *address,
580 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
581 ARGS&&... arguments);
582#endif
583
584 /// Call the `ELEMENT_TYPE` destructor for the object at the specified
585 /// `address` but do not deallocate the memory at `address`.
586 template <class ELEMENT_TYPE>
587 void destroy(ELEMENT_TYPE *address);
588
589 // ACCESSORS
590
591 /// Return the address of the object referred to by the specified `x`
592 /// reference, even if the (template parameter) `TYPE` overloads the
593 /// unary `operator&`.
596
597 /// Return the maximum number of elements of (template parameter) `TYPE`
598 /// that can be allocated using this allocator. Note that there is no
599 /// guarantee that attempts at allocating fewer elements than the value
600 /// returned by @ref max_size will not throw.
602
603 /// Return the address of the memory resource supplied on construction.
605
606 /// Return a default-constructed `polymorphic_allocator`.
608
609 // HIDDEN FRIENDS
610
611 /// Return `true` if memory allocated from either of the specified `a`
612 /// or `b` allocators can be deallocated from the other; otherwise
613 /// return `false`. This operator is selected by overload resolution if
614 /// at least one argument is a specialization of `polymorphic_allocator`
615 /// and the other is either the same specialization or is convertible to
616 /// `polymorphic_allocator`. Note that this operator is a "hidden
617 /// friend" so that it is found by only by ADL and is not considered
618 /// during overload resoution if neither argument is a specialization of
619 /// `polymorphic_allocator`; see
620 /// https://cplusplus.github.io/LWG/issue3683.
621 friend
624 {
625 return a.resource() == b.resource() || *a.resource() == *b.resource();
626 }
627
628 /// Return `true` if memory allocated from either of the specified `a`
629 /// or `b` allocators cannot necessarily be deallocated from the other;
630 /// otherwise return `false`. This operator is selected by overload
631 /// resolution if at least one argument is a specialization of
632 /// `polymorphic_allocator` and the other is either the same
633 /// specialization or is convertible to `polymorphic_allocator`. Note
634 /// that this operator is a "hidden friend" so that it is found by only
635 /// by ADL and is not considered during overload resoution if neither
636 /// argument is a specialization of `polymorphic_allocator`; see
637 /// https://cplusplus.github.io/LWG/issue3683.
638 friend
641 {
642 return a.resource() != b.resource() && *a.resource() != *b.resource();
643 }
644};
645
646// FREE FUNCTIONS
647
648/// Return `true` if memory allocated from either of the specified `a` or
649/// `b` allocators can be deallocated from the other; otherwise return
650/// `false`. Note that, when `T1` and `T2` are different, this free
651/// operator is a better match than the hidden friend operator, which would
652/// otherwise be ambiguous.
653template <class T1, class T2>
654bool operator==(const polymorphic_allocator<T1>& a,
656
657/// Return `true` if memory allocated from either of the specified `a` or
658/// `b` allocators cannot necessarily be deallocated from the other;
659/// otherwise return `false`. Note that, when `T1` and `T2` are different,
660/// this free operator is a better match than the hidden friend operator,
661/// which would otherwise be ambiguous.
662template <class T1, class T2>
663bool operator!=(const polymorphic_allocator<T1>& a,
665
666} // close namespace bsl
667
668#endif // End C++03 code
669
670namespace bsl {
671
672 // ====================================================
673 // class allocator_traits<polymorphic_allocator<TYPE> >
674 // ====================================================
675
676/// This `struct` template provides a specialization of the
677/// `allocator_traits` class template for `bsl::polymorphic_allocator`.
678/// This specialization is not strictly necessary, but its presence speeds
679/// up compilation by bypassing a significant amount of metaprogramming.
680template <class TYPE>
682
683 // PUBLIC TYPES
685 typedef TYPE value_type;
686
687 typedef TYPE *pointer;
688 typedef const TYPE *const_pointer;
689 typedef void *void_pointer;
690 typedef const void *const_void_pointer;
691 typedef std::ptrdiff_t difference_type;
692 typedef std::size_t size_type;
693
694#ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES
695 template <class TYPE2>
696 using rebind_alloc = polymorphic_allocator<TYPE2>;
697
698 template <class TYPE2>
699 using rebind_traits = allocator_traits<polymorphic_allocator<TYPE2> >;
700#else
701 template <class TYPE2>
702 struct rebind_alloc : polymorphic_allocator<TYPE2> {
704 : polymorphic_allocator<TYPE2>()
705 {
706 }
707
708 /// Convert from anything that can be used to cosntruct the base type.
709 /// This might be better if SFINAE-ed out using `is_convertible`, but
710 /// stressing older compilers more seems unwise.
711 template <typename ARG>
712 rebind_alloc(const ARG& allocatorArg)
713 : polymorphic_allocator<TYPE2>(allocatorArg)
714 {
715 }
716 };
717
718 template <class TYPE2>
719 struct rebind_traits : allocator_traits<polymorphic_allocator<TYPE2> > {
720 };
721#endif
722
724 {
725 return m.allocate(n);
726 }
727
729 size_type n,
730 const_void_pointer /* hint */)
731 {
732 return m.allocate(n);
733 }
734
736 {
737 m.deallocate(p, n);
738 }
739
740 template <class TYPE2>
741 static void construct(allocator_type& m,
742 TYPE2 *p)
743 {
744 m.construct(p);
745 }
746
747#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=14
748 template <class TYPE2, class ARG1, class... ARGS>
749 static void construct(allocator_type& m,
750 TYPE2 *p,
751 ARG1& argument1,
752 ARGS&&... arguments)
753 {
754 m.construct(p,
755 argument1,
756 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
757 }
758
759 template <class TYPE2, class ARG1, class... ARGS>
760 static void construct(allocator_type& m,
761 TYPE2 *p,
762 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
763 ARGS&&... arguments)
764 {
765 m.construct(p,
766 BSLS_COMPILERFEATURES_FORWARD(ARG1, argument1),
767 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
768 }
769#endif
770
771 template <class TYPE2>
772 static void destroy(allocator_type&, TYPE2 *p)
773 {
774 p->~TYPE2();
775 }
776
779 {
780 // Return the largest value, 'v', such that 'v * sizeof(T)' fits in a
781 // 'size_type'. Note that we cannot call
782 // 'allocator_type::max_size()' because that method does not exist in
783 // the C++17 standard library.
784
785 return (~size_type(0)) / sizeof(TYPE);
786 }
787
788 // Allocator propagation traits
789 static allocator_type
794
799};
800
801} // close namespace bsl
802
803// ============================================================================
804// TEMPLATES AND INLINE FUNCTION DEFINITIONS
805// ============================================================================
806
807// TRAITS
808namespace bsl {
809
810/// Note that the `bsl::is_trivially_copyable` trait automatically sets the
811/// `bslmf::IsBitwiseMoveable` trait.
812template <class TYPE>
814} // close namespace bsl
815
816
817namespace bslma {
818
819/// Declare `polymorphic_allocator` as a C++11 compatible allocator for
820/// all versions of C++.
821template <class TYPE>
826
827/// An allocator is not *itself* an allocator-aware type, even though it is
828/// convertible from `bsl::Allocator *`.
829template <class TYPE>
833
834} // close namespace bslma
835
836namespace bslmf {
837
838template <class TYPE>
841
842} // close namespace bslmf
843
844
845#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
846
847 // ----------------------------------------------
848 // class template std::pmr::polymorphic_allocator
849 // ----------------------------------------------
850
851// FREE FUNCTIONS
852
853// Put extra operators in the 'std::pmr' namespace, not 'bsl' namespace.
854template <class TYPE>
855inline
856bool std::pmr::operator==(const std::pmr::polymorphic_allocator<TYPE>& a,
857 const BSLMF_POLYMORPHICALLOCATOR_NODEDUCE_T(TYPE)& b)
859{
860 return a.resource() == b.resource() || *a.resource() == *b.resource();
861}
862
863template <class TYPE>
864inline
865bool std::pmr::operator==(const BSLMF_POLYMORPHICALLOCATOR_NODEDUCE_T(TYPE)& a,
866 const std::pmr::polymorphic_allocator<TYPE>& b)
868{
869 return a.resource() == b.resource() || *a.resource() == *b.resource();
870}
871
872template <class TYPE>
873inline
874bool std::pmr::operator!=(const std::pmr::polymorphic_allocator<TYPE>& a,
875 const BSLMF_POLYMORPHICALLOCATOR_NODEDUCE_T(TYPE)& b)
877{
878 return a.resource() != b.resource() && *a.resource() != *b.resource();
879}
880
881template <class TYPE>
882inline
883bool std::pmr::operator!=(const BSLMF_POLYMORPHICALLOCATOR_NODEDUCE_T(TYPE)& a,
884 const std::pmr::polymorphic_allocator<TYPE>& b)
886{
887 return a.resource() != b.resource() && *a.resource() != *b.resource();
888}
889
890#else // if ! defined(BSLS_LIBRARYFEATURES_HAS_CPP17_PMR)
891
892namespace bsl {
893
894 // -----------------------------------------
895 // class template bsl::polymorphic_allocator
896 // -----------------------------------------
897
898// CREATORS
899template <class TYPE>
901: d_resource(BloombergLP::bslma::Default::defaultAllocator())
902{
903}
904
905template <class TYPE>
906inline
912
913#ifndef BSLS_COMPILERFEATURES_SUPPORT_DEFAULTED_FUNCTIONS
914// In C++11 or later, this copy constructor is defaulted.
915template <class TYPE>
916inline
919: d_resource(other.resource())
920{
921}
922#endif
923
924template <class TYPE>
925template<class ANY_TYPE>
926inline
933
934// MANIPULATORS
935template <class TYPE>
936inline
938{
939 const size_t k_TYPE_ALIGNMENT =
940 BloombergLP::bsls::AlignmentFromType<TYPE>::VALUE;
941
942 if (n > this->max_size()) {
943 BloombergLP::bsls::BslExceptionUtil::throwBadAlloc();
944 }
945
946 return static_cast<TYPE *>(d_resource->allocate(n * sizeof(TYPE),
947 k_TYPE_ALIGNMENT));
948}
949
950#ifndef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY
951template <class TYPE>
952inline
953TYPE *
954polymorphic_allocator<TYPE>::allocate(std::size_t n, const void * /* hint */)
955{
956 return this->allocate(n);
957}
958#endif
959
960template <class TYPE>
961inline
962void polymorphic_allocator<TYPE>::deallocate(TYPE *p, std::size_t n)
963{
964 const std::size_t k_TYPE_ALIGNMENT =
965 BloombergLP::bsls::AlignmentFromType<TYPE>::VALUE;
966
967 d_resource->deallocate(p, n * sizeof(TYPE), k_TYPE_ALIGNMENT);
968}
969
970template <class TYPE>
971template <class ELEMENT_TYPE>
972inline
973void polymorphic_allocator<TYPE>::construct(ELEMENT_TYPE *address)
974{
975 BloombergLP::bslma::ConstructionUtil::construct(address, *this);
976}
977
978#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
979template <class TYPE>
980template <class ELEMENT_TYPE, class ARG1, class... ARGS>
981inline
982void polymorphic_allocator<TYPE>::construct(ELEMENT_TYPE *address,
983 ARG1& argument1,
984 ARGS&&... arguments)
985{
986 BloombergLP::bslma::ConstructionUtil::construct(
987 address,
988 *this,
989 argument1,
990 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
991}
992
993template <class TYPE>
994template <class ELEMENT_TYPE, class ARG1, class... ARGS>
995inline
997 ELEMENT_TYPE *address,
998 BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1,
999 ARGS&&... arguments)
1000{
1001 BloombergLP::bslma::ConstructionUtil::construct(
1002 address,
1003 *this,
1004 BSLS_COMPILERFEATURES_FORWARD(ARG1, argument1),
1005 BSLS_COMPILERFEATURES_FORWARD(ARGS, arguments)...);
1006}
1007#endif
1008
1009template <class TYPE>
1010template <class ELEMENT_TYPE>
1011inline
1012void polymorphic_allocator<TYPE>::destroy(ELEMENT_TYPE *address)
1013{
1014 BloombergLP::bslma::DestructionUtil::destroy(address);
1015}
1016
1017
1018// ACCESSORS
1019template <class TYPE>
1020inline
1023{
1024 return BloombergLP::bsls::Util::addressOf(x);
1025}
1026
1027template <class TYPE>
1028inline
1031{
1032 return BloombergLP::bsls::Util::addressOf(x);
1033}
1034
1035template <class TYPE>
1039{
1040 // Return the largest value, 'v', such that 'v * sizeof(T)' fits in a
1041 // 'size_type'.
1042
1043 return (~size_type(0)) / sizeof(TYPE);
1044}
1045
1046template <class TYPE>
1047inline
1049{
1050 return d_resource;
1051}
1052
1053template <class TYPE>
1054inline
1060
1061} // Close namespace bsl
1062
1063// FREE FUNCTIONS
1064template <class T1, class T2>
1065inline
1066bool
1067bsl::operator==(const bsl::polymorphic_allocator<T1>& a,
1069{
1070 return a.resource() == b.resource() || *a.resource() == *b.resource();
1071}
1072
1073template <class T1, class T2>
1074inline
1075bool
1078{
1079 return a.resource() != b.resource() && *a.resource() != *b.resource();
1080}
1081
1082#endif // defined(BSLS_LIBRARYFEATURES_HAS_CPP17_PMR)
1083
1084#endif // End C++11 code
1085
1086#endif // ! defined(INCLUDED_BSLMA_POLYMORPHICALLOCATOR)
1087
1088// ----------------------------------------------------------------------------
1089// Copyright 2022 Bloomberg Finance L.P.
1090//
1091// Licensed under the Apache License, Version 2.0 (the "License");
1092// you may not use this file except in compliance with the License.
1093// You may obtain a copy of the License at
1094//
1095// http://www.apache.org/licenses/LICENSE-2.0
1096//
1097// Unless required by applicable law or agreed to in writing, software
1098// distributed under the License is distributed on an "AS IS" BASIS,
1099// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1100// See the License for the specific language governing permissions and
1101// limitations under the License.
1102// ----------------------------- END-OF-FILE ----------------------------------
1103
1104/** @} */
1105/** @} */
1106/** @} */
Definition bslma_memoryresource.h:441
BSLS_ANNOTATION_NODISCARD void * allocate(size_t bytes, size_t alignment=k_MAX_ALIGN)
Definition bslma_memoryresource.h:541
void deallocate(void *p, size_t bytes, size_t alignment=k_MAX_ALIGN)
Definition bslma_memoryresource.h:547
Definition bslma_polymorphicallocator.h:452
friend bool operator==(const polymorphic_allocator &a, const polymorphic_allocator &b) BSLS_KEYWORD_NOEXCEPT
Definition bslma_polymorphicallocator.h:622
BSLS_ANNOTATION_NODISCARD TYPE * allocate(std::size_t n)
Definition bslma_polymorphicallocator.h:937
memory_resource * resource() const
Return the address of the memory resource supplied on construction.
Definition bslma_polymorphicallocator.h:1048
TYPE * pointer
Definition bslma_polymorphicallocator.h:465
const_pointer address(const_reference x) const
Definition bslma_polymorphicallocator.h:1030
void construct(ELEMENT_TYPE *address, ARG1 &argument1, ARGS &&... arguments)
Definition bslma_polymorphicallocator.h:982
friend bool operator!=(const polymorphic_allocator &a, const polymorphic_allocator &b) BSLS_KEYWORD_NOEXCEPT
Definition bslma_polymorphicallocator.h:639
void construct(ELEMENT_TYPE *address)
Definition bslma_polymorphicallocator.h:973
const TYPE * const_pointer
Definition bslma_polymorphicallocator.h:466
polymorphic_allocator(const polymorphic_allocator &original) BSLS_KEYWORD_NOEXCEPT
Definition bslma_polymorphicallocator.h:918
polymorphic_allocator() BSLS_KEYWORD_NOEXCEPT
Definition bslma_polymorphicallocator.h:900
std::ptrdiff_t difference_type
Definition bslma_polymorphicallocator.h:464
void construct(ELEMENT_TYPE *address, BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1, ARGS &&... arguments)
Definition bslma_polymorphicallocator.h:996
TYPE & reference
Definition bslma_polymorphicallocator.h:467
std::size_t size_type
Definition bslma_polymorphicallocator.h:463
BSLS_KEYWORD_CONSTEXPR size_type max_size() const
Definition bslma_polymorphicallocator.h:1038
polymorphic_allocator select_on_container_copy_construction() const
Return a default-constructed polymorphic_allocator.
Definition bslma_polymorphicallocator.h:1056
polymorphic_allocator(const polymorphic_allocator< ANY_TYPE > &original) BSLS_KEYWORD_NOEXCEPT
Definition bslma_polymorphicallocator.h:928
TYPE value_type
Definition bslma_polymorphicallocator.h:469
void deallocate(TYPE *p, std::size_t n)
Definition bslma_polymorphicallocator.h:962
const TYPE & const_reference
Definition bslma_polymorphicallocator.h:468
pointer address(reference x) const
Definition bslma_polymorphicallocator.h:1022
void destroy(ELEMENT_TYPE *address)
Definition bslma_polymorphicallocator.h:1012
#define BSLS_ANNOTATION_NODISCARD
Definition bsls_annotation.h:373
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2012
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2018
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_CONSTEXPR
Definition bsls_keyword.h:588
#define BSLS_KEYWORD_DELETED
Definition bsls_keyword.h:609
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
bool operator!=(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
bool operator==(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
Definition bdlb_printmethods.h:283
bool operator!=(const memory_resource &a, const memory_resource &b)
Definition balxml_encoderoptions.h:68
Definition bdlbb_blob.h:576
rebind_alloc(const ARG &allocatorArg)
Definition bslma_polymorphicallocator.h:712
rebind_alloc()
Definition bslma_polymorphicallocator.h:703
false_type propagate_on_container_copy_assignment
Definition bslma_polymorphicallocator.h:796
TYPE value_type
Definition bslma_polymorphicallocator.h:685
std::ptrdiff_t difference_type
Definition bslma_polymorphicallocator.h:691
false_type propagate_on_container_swap
Definition bslma_polymorphicallocator.h:798
polymorphic_allocator< TYPE > allocator_type
Definition bslma_polymorphicallocator.h:684
static pointer allocate(allocator_type &m, size_type n)
Definition bslma_polymorphicallocator.h:723
static BSLS_KEYWORD_CONSTEXPR size_type max_size(const allocator_type &)
Definition bslma_polymorphicallocator.h:778
std::size_t size_type
Definition bslma_polymorphicallocator.h:692
static void construct(allocator_type &m, TYPE2 *p)
Definition bslma_polymorphicallocator.h:741
static void construct(allocator_type &m, TYPE2 *p, ARG1 &argument1, ARGS &&... arguments)
Definition bslma_polymorphicallocator.h:749
const TYPE * const_pointer
Definition bslma_polymorphicallocator.h:688
TYPE * pointer
Definition bslma_polymorphicallocator.h:687
false_type propagate_on_container_move_assignment
Definition bslma_polymorphicallocator.h:797
const void * const_void_pointer
Definition bslma_polymorphicallocator.h:690
static void destroy(allocator_type &, TYPE2 *p)
Definition bslma_polymorphicallocator.h:772
static void deallocate(allocator_type &m, pointer p, size_type n)
Definition bslma_polymorphicallocator.h:735
void * void_pointer
Definition bslma_polymorphicallocator.h:689
false_type is_always_equal
Definition bslma_polymorphicallocator.h:795
static void construct(allocator_type &m, TYPE2 *p, BSLS_COMPILERFEATURES_FORWARD_REF(ARG1) argument1, ARGS &&... arguments)
Definition bslma_polymorphicallocator.h:760
static allocator_type select_on_container_copy_construction(const allocator_type &)
Definition bslma_polymorphicallocator.h:790
static pointer allocate(allocator_type &m, size_type n, const_void_pointer)
Definition bslma_polymorphicallocator.h:728
Definition bslma_allocatortraits.h:1061
BloombergLP::bslma::AllocatorTraits_SizeType< ALLOCATOR_TYPE >::type size_type
Definition bslma_allocatortraits.h:1165
ALLOCATOR_TYPE allocator_type
Definition bslma_allocatortraits.h:1144
Definition bslmf_integralconstant.h:244
Definition bslmf_istriviallycopyable.h:329
Definition bslma_polymorphicallocator.h:477
polymorphic_allocator< ANY_TYPE > other
Definition bslma_polymorphicallocator.h:478
Definition bslma_isstdallocator.h:201
Definition bslma_usesbslmaallocator.h:343
Definition bslmf_isbitwiseequalitycomparable.h:499