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