BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslma_aamodel.h
Go to the documentation of this file.
1/// @file bslma_aamodel.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_aamodel.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_AAMODEL
9#define INCLUDED_BSLMA_AAMODEL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_aamodel bslma_aamodel
15/// @brief Provide metafunctions to detect a type's allocator-awareness model.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_aamodel
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_aamodel-purpose"> Purpose</a>
25/// * <a href="#bslma_aamodel-classes"> Classes </a>
26/// * <a href="#bslma_aamodel-description"> Description </a>
27/// * <a href="#bslma_aamodel-supported-allocator-aware-models"> Supported Allocator-Aware (AA) models </a>
28/// * <a href="#bslma_aamodel-allocator-aware-model-tags"> Allocator-Aware (AA) model tags </a>
29/// * <a href="#bslma_aamodel-aa-model-metafunctions"> AA-model metafunctions </a>
30/// * <a href="#bslma_aamodel-usage"> Usage </a>
31/// * <a href="#bslma_aamodel-example-1-conditionally-passing-an-allocator-to-a-constructor"> Example 1: Conditionally Passing an Allocator to a Constructor </a>
32/// * <a href="#bslma_aamodel-example-2-choose-an-implementation-based-on-allocator-aware-model"> Example 2: Choose an Implementation Based on Allocator-Aware (AA) model </a>
33///
34/// # Purpose {#bslma_aamodel-purpose}
35/// Provide metafunctions to detect a type's allocator-awareness model.
36///
37/// # Classes {#bslma_aamodel-classes}
38///
39/// - AAModelNone: Tag `struct` representing no AA model
40/// - AAModelPmr: Tag for the **pmr-AA** model (`polymorphic_allocator`)
41/// - AAModelBsl: Tag for the **bsl-AA** model (`bsl::allocator`)
42/// - AAModelLegacy: Tag for the **legacy-AA** model (`bslma::Allocator*`)
43/// - AAModelStl: Tag for the **stl-AA** model (non-bsl, non-pmr STL alloc)
44/// - AAModelIsSupported: Metafunction to detect if type `T` supports model `M`
45/// - AAModel: Metafunction to detect the AA model implemented by a type `T`
46///
47/// @see bslma_allocator, bslma_bslallocator
48///
49/// # Description {#bslma_aamodel-description}
50/// This component provides five tag `struct`s (`AAModelNone`,
51/// `AAModelLegacy`, `AAModelBsl`, `AAModelPmr`, and `AAModelStl`) and a pair of
52/// metafunction classes (`AAModelIsSupported<TYPE, MODEL>` and `AAModel<TYPE>`)
53/// that allow generic allocator-handling facilities -- such as those that
54/// construct allocator-aware (a.k.a., AA) objects, extract the allocator from
55/// AA objects, and manage propagation of allocators from a container to its
56/// contained elements -- to determine, at compile time, the AA model of the
57/// type(s) they work with.
58///
59/// ## Supported Allocator-Aware (AA) models {#bslma_aamodel-supported-allocator-aware-models}
60///
61///
62/// The AA model supported by a type `T` is determined primarily by the type of
63/// allocator used by `T` to allocate memory:
64///
65/// * If `T` does not use an externally supplied allocator, then it is not AA.
66/// * If `T` uses the address of a `bslma::Allocator`, then it is **legacy-AA**.
67/// Most older AA classes developed at Bloomberg are **legacy-AA**. The value
68/// of `bslma::UsesBslmaAllocator<T>::value` must be true for a type to be
69/// detected as supporting the **legacy-AA** model.
70/// * If `T` uses an instantiation of `bsl::allocator`, then it is **bsl-AA**.
71/// Most newer AA classes developed at Bloomberg are **bsl-AA**. `T` is
72/// automatically detectable as supporting the **bsl-AA** model if there exists
73/// a nested type `T::allocator_type` that is convertible from
74/// `bsl::allocator<char>`.
75/// * If `T` uses an instantiation of `bsl::polymorphic_allocator`, then it is
76/// **pmr-AA**. `T` will be automatically detectable as supporting the
77/// **pmr-AA** model if there exists a nested type `T::allocator_type` that is
78/// convertible from `bsl::polymorphic_allocator<char>`.
79/// * If `T` uses an STL-style allocator other than `bsl::allocator` or
80/// `bsl::polymorphic_allocator`, then it is **stl-AA**. For the purposes of
81/// this component, any class having an `allocator_type` member that is not
82/// convertible from `bsl::allocator` or `bsl::polymorphic_allocator` is
83/// assumed to be fall into this category. For example, `bslstl::vector` is
84/// **stl-AA** if it is instantiated with a third-party STL-compliant
85/// allocator.
86///
87/// Note that a single type can support more than one AA model. For example,
88/// any type that is **bsl-AA** can be constructed with a `bsl::Allocator` pointer
89/// and, thus, can be said to support the **legacy-AA** model as well. Similarly,
90/// all AA types are assumed to be constructible without specifying an allocator
91/// (typically using a default-initialized allocator value) and, thus, can be
92/// used as non-AA types.
93///
94/// ## Allocator-Aware (AA) model tags {#bslma_aamodel-allocator-aware-model-tags}
95///
96///
97/// Each of the above models has a corresponding *model tag* `struct` in this
98/// component. A *model tag* can be thought of as an enumerator except that,
99/// rather than being a simple integral value within an `enum`, each one is a
100/// `struct` that has no non-static data members, is derived from an
101/// instantiation of `bsl::integral_constant`, and has a `type` member `typedef`
102/// alias for itself. By representing each model as a separate *type* rather
103/// than a simple *value*, these tag types are more versatile when used for
104/// metaprogramming. The table below lists the `value` constant for each
105/// **model tag** struct:
106/// @code
107/// +---------------+-------+
108/// | model tag | value |
109/// +---------------+-------+
110/// | AAModelNone | 0 |
111/// | AAModelPmr | 1 |
112/// | AAModelBsl | 2 |
113/// | AAModelLegacy | 3 |
114/// | AAModelStl | 4 |
115/// +---------------+-------+
116/// @endcode
117/// Note that these values are roughly in order of "pickyness" of the model: A
118/// *legacy-AA* type's constructors accept only allocators convertible to
119/// `bslma::Allocator *` whereas a **pmr-AA** type is less picky in that its
120/// constructors also accept allocators convertible to
121/// `bsl::polymorphic_allocator` (including `bsl::allocator`). The models are
122/// not fully ordered in that, for example, **stl-AA** is orthogonal to the rest
123/// and is neither more nor less picky than **legacy-AA**.
124///
125/// ## AA-model metafunctions {#bslma_aamodel-aa-model-metafunctions}
126///
127///
128/// The metafunctions `AAModel<T>` and `AAModelIsSupported<T,M>` are used for
129/// compile-time dispatch of generic code for different allocator models. This
130/// subsection describes the criteria by which these metafunctions determine the
131/// AA model for a type `T`. The information here is not critical for
132/// understanding the use of this component, so readers are welcome to skip
133/// forward to the usage examples, below.
134///
135/// With the exception of **legacy-AA**, AA types generally adhere to the basic
136/// interface pattern shown here:
137/// @code
138/// class AAType {
139/// // ... (private members)
140/// public:
141/// // TYPES
142/// typedef some-type allocator_type;
143///
144/// // CREATORS
145/// // ... (constructors that optionally take an 'allocator_type' argument)
146/// ~AAType();
147///
148/// // MANIPULATORS
149/// // ...
150///
151/// // ACCESSORS
152/// // ...
153/// allocator_type get_allocator() const;
154/// };
155/// @endcode
156/// The metafunctions in this component test for the existence of the
157/// `allocator_type` member. If `T::allocator_type` exists, then `T` is assumed
158/// to support the **stl-AA** model. If, additionally,
159/// `bsl::polymorphic_allocator<char>` and/or `bsl::allocator<char>` are
160/// convertible to `T::allocator_type` then `T` supports the **pmr-AA** and/or
161/// **bsl-AA** models, respectively. The metafunctions do not require that AA
162/// constructors exist nor that the @ref get_allocator member function exists.
163///
164/// The interface for a **legacy-AA** type is somewhat different:
165/// @code
166/// class LegacyAAType {
167/// // ... (private members)
168/// public:
169/// // TRAITS
170/// BSLMF_NESTED_TRAIT_DECLARATION(LegacyAAType,
171/// bslma::UsesBslmaAllocator);
172///
173/// // CREATORS
174/// // ... (constructors that optionally take an 'bslma::Allocator*' arg)
175/// ~LegacyAAType();
176///
177/// // MANIPULATORS
178/// // ...
179///
180/// // ACCESSORS
181/// // ...
182/// bslma::Allocator *allocator() const;
183/// };
184/// @endcode
185/// If `bslma::UsesBslmaAllocator<T>::value` is `true`, then the metafunctions
186/// assume that `T` supports the **legacy-AA** model. Again, the presence of
187/// appropriate allocators or the `allocator` accessor are not required.
188///
189/// ## Usage {#bslma_aamodel-usage}
190///
191///
192///
193/// ### Example 1: Conditionally Passing an Allocator to a Constructor {#bslma_aamodel-example-1-conditionally-passing-an-allocator-to-a-constructor}
194///
195///
196/// This example demonstrates the use of `AAModelIsSupported` to choose an
197/// appropriate overload for AA constructors. Consider a **bsl-AA** class,
198/// `Wrapper`, that wraps an object of template-parameter type, `TYPE`. First,
199/// we define the data members:
200/// @code
201/// /// Wrap an object of type `TYPE`.
202/// template <class TYPE>
203/// class Wrapper {
204///
205/// // DATA
206/// bsl::allocator<char> d_allocator;
207/// TYPE d_object;
208///
209/// public:
210/// // TYPES
211/// typedef bsl::allocator<char> allocator_type;
212/// @endcode
213/// Next, we define the constructors. The constructors for `Wrapper` would all
214/// take an optional `allocator_type` argument, but the `d_object` member might
215/// or might not be constructed with an allocator argument. To handle the
216/// allocator correctly, therefore, we choose to have two versions of each
217/// constructor: one that is invoked if `TYPE` is AA and one that is invoked if
218/// it is not. Since both constructors have the same argument list, we must
219/// make them templates and distinguish them using SFINAE so that only one
220/// instantiation is valid, i.e., by using `enable_if` along with the
221/// `AAModelIsSupported`:
222/// @code
223/// // CREATORS
224///
225/// /// Construct a `Wrapper` using the specified `a` allocator, passing
226/// /// the allocator to the wrapped object. This constructor will not
227/// /// participate in overload resolution unless `TYPE` supports the
228/// /// legacy allocator-awareness model (**legacy-AA**).
229/// template <class ALLOC>
230/// explicit
231/// Wrapper(const ALLOC& a,
232/// typename bsl::enable_if<
233/// bsl::is_convertible<ALLOC,allocator_type>::value
234/// && bslma::AAModelIsSupported<TYPE,bslma::AAModelLegacy>::value,
235/// int
236/// >::type = 0)
237/// : d_allocator(a), d_object(d_allocator.mechanism()) { }
238///
239/// /// Construct a `Wrapper` using the specified `a` allocator,
240/// /// constructing the wrapped object without an explicit allocator.
241/// /// This constructor will not participate in overload resolution if
242/// /// `TYPE` supports the legacy allocator-awareness model
243/// /// (**legacy-AA**).
244/// template <class ALLOC>
245/// explicit
246/// Wrapper(const ALLOC& a,
247/// typename bsl::enable_if<
248/// bsl::is_convertible<ALLOC,allocator_type>::value
249/// && !bslma::AAModelIsSupported<TYPE,bslma::AAModelLegacy>::value,
250/// int
251/// >::type = 0)
252/// : d_allocator(a), d_object() { }
253/// @endcode
254/// Support for ***bsl-AA*** implies support for **legacy-AA**, so the example
255/// above needs to test for only the latter model; the first constructor
256/// overload is selected if `TYPE` implements either AA model. Similarly
257/// `d_allocator.mechanism()` yields a common denominator type,
258/// `bslma::Allocator *` that can be passed to the constructor for `d_object`,
259/// regardless of its preferred AA model. The second overload is selected for
260/// types that do *not* support the **legacy-AA** (or **bsl-AA**) model. Note
261/// that this example, though functional, does not handle all cases; e.g., it
262/// does not handle types whose allocator constructor parameter is preceded by
263/// `bsl::allocator_arg_t`. See higher-level components such as
264/// @ref bslma_contructionutil for a more comprehensive treatment of AA constructor
265/// variations.
266///
267/// Next, we finish up our class by creating accessors to get the allocator and
268/// wrapped object:
269/// @code
270/// // ACCESSORS
271///
272/// /// Return the allocator used to construct this object.
273/// const allocator_type get_allocator() const { return d_allocator; }
274///
275/// const TYPE& value() const { return d_object; }
276/// };
277/// @endcode
278/// Now, to see the effect of these constructors, we'll use a simple AA class,
279/// `SampleAAType` that does nothing more than hold the allocator:
280/// @code
281/// /// Sample AA class that adheres to the bsl-AA interface.
282/// class SampleAAType {
283///
284/// // DATA
285/// bsl::allocator<char> d_allocator;
286///
287/// public:
288/// // TYPES
289/// typedef bsl::allocator<char> allocator_type;
290///
291/// // CREATORS
292/// explicit SampleAAType(const allocator_type& alloc = allocator_type())
293/// : d_allocator(alloc) { }
294/// SampleAAType(const SampleAAType&) { }
295///
296/// // MANIPULATORS
297/// SampleAAType& operator=(const SampleAAType&) { return *this; }
298///
299/// // ACCESSORS
300/// allocator_type get_allocator() const { return d_allocator; }
301/// };
302/// @endcode
303/// Finally, in our main program, create an allocator and pass it to a couple of
304/// `Wrapper` objects, one instantiated with `int` and the other instantiated
305/// with our `SampleAAType`. We verify that both were constructed
306/// appropriately, with the allocator being used by the `SampleAAType` object,
307/// as desired:
308/// @code
309/// void main()
310/// {
311/// bslma::TestAllocator alloc;
312///
313/// Wrapper<int> w1(&alloc);
314/// assert(&alloc == w1.get_allocator());
315/// assert(0 == w1.value());
316///
317/// Wrapper<SampleAAType> w2(&alloc);
318/// assert(&alloc == w2.get_allocator());
319/// assert(&alloc == w2.value().get_allocator());
320/// }
321/// @endcode
322/// Note that, even though `SampleAAType` conforms to the **bsl-AA** interface,
323/// it is also supports the **legacy-AA** model because `bslma::Allocator *` is
324/// convertible to `bsl::allocator`.
325///
326/// ### Example 2: Choose an Implementation Based on Allocator-Aware (AA) model {#bslma_aamodel-example-2-choose-an-implementation-based-on-allocator-aware-model}
327///
328///
329/// This example demonstrates the use of `AAModel` to dispatch among several
330/// implementations based on the AA model preferred by a parameter type. We
331/// would like a uniform way to get the allocator used by an object. We'll
332/// define a utility class, `Util`, containing a static member function
333/// template, `getAllocator(const TYPE& obj)` returning a `bsl::allocator<char>`
334/// as follows:
335///
336/// * If `TYPE` is **bsl-AA**, return `obj.get_allocator()`.
337/// * If `TYPE` is **legacy-AA**, return `bsl::allocator<char>(obj.allocator())`.
338/// * If `TYPE` is not AA, return `bsl::allocator<char>()`.
339/// * If `TYPE` is AA but not one of the above, compilation will fail.
340///
341/// We'll use `AAModel<TYPE>` to dispatch to one of three implementations of
342/// `getAllocator`.
343///
344/// First, we declare the `Util` class and three private overloaded
345/// implemention functions, each taking an argument of a different AA model
346/// tag:
347/// @code
348/// /// Namespace for functions that operate on AA types.
349/// class Util {
350///
351/// template <class TYPE>
352/// static bsl::allocator<char> getAllocatorImp(const TYPE& obj,
353/// bslma::AAModelBsl)
354/// { return obj.get_allocator(); }
355/// template <class TYPE>
356/// static bsl::allocator<char> getAllocatorImp(const TYPE& obj,
357/// bslma::AAModelLegacy)
358/// { return obj.allocator(); }
359/// template <class TYPE>
360/// static bsl::allocator<char> getAllocatorImp(const TYPE&,
361/// bslma::AAModelNone)
362/// { return bsl::allocator<char>(); }
363/// @endcode
364/// Next, we dispatch to one of the implementation functions using
365/// `AAModel<TYPE>` to yield a tag that indicates the AA model used by `TYPE`.
366/// @code
367///
368/// public:
369/// // CLASS METHODS
370/// template <class TYPE>
371/// static bsl::allocator<char> getAllocator(const TYPE& obj)
372/// { return getAllocatorImp(obj, bslma::AAModel<TYPE>()); }
373/// };
374/// @endcode
375/// Now, to check all of the possibilities, we create a minimal AA type sporting
376/// the **legacy-AA** interface:
377/// @code
378/// /// Sample AA class that adheres to the bsl-AA interface.
379/// class SampleLegacyAAType {
380///
381/// // DATA
382/// bslma::Allocator *d_allocator_p;
383///
384/// public:
385/// // TRAITS
386/// BSLMF_NESTED_TRAIT_DECLARATION(SampleLegacyAAType,
387/// bslma::UsesBslmaAllocator);
388///
389/// // CREATORS
390/// explicit SampleLegacyAAType(bslma::Allocator *a =0)
391/// : d_allocator_p(a) { }
392///
393/// // ACCESSORS
394/// bslma::Allocator *allocator() const { return d_allocator_p; }
395/// };
396/// @endcode
397/// Finally, we create objects of `SampleAAType` and `SampleLegacyAAType` using
398/// different allocators as well as an object of type `float` (which, of course
399/// is not AA), and verify that `Util::getAllocator` returns the correct
400/// allocator for each.
401/// @code
402/// void main()
403/// {
404/// bslma::TestAllocator ta1, ta2;
405///
406/// SampleAAType obj1(&ta1);
407/// SampleLegacyAAType obj2(&ta2);
408/// float obj3 = 0.0;
409///
410/// assert(Util::getAllocator(obj1) == &ta1);
411/// assert(Util::getAllocator(obj2) == &ta2);
412/// assert(Util::getAllocator(obj3) == bslma::Default::defaultAllocator());
413/// }
414/// @endcode
415/// @}
416/** @} */
417/** @} */
418
419/** @addtogroup bsl
420 * @{
421 */
422/** @addtogroup bslma
423 * @{
424 */
425/** @addtogroup bslma_aamodel
426 * @{
427 */
428
429
430#include <bslscm_version.h>
431
432#include <bslma_allocator.h>
435#include <bslma_bslallocator.h>
437
438#include <bslmf_conditional.h>
440#include <bslmf_tag.h>
441#include <bslmf_usesallocator.h>
442#include <bslmf_voidtype.h>
443
444
445namespace bslma {
446
447// FORWARD DECLARATIONS
448template <class TYPE,
449 class MODEL1,
450 class MODEL2 = void,
451 class MODEL3 = void,
452 class MODEL4 = void,
453 class MODEL5 = void> struct AAModel_Imp;
454
455 // ==================
456 // struct AAModelNone
457 // ==================
458
459/// Model tag for non-AA types.
461
462 // TYPES
464};
465
466 // =================
467 // struct AAModelPmr
468 // =================
469
470/// Model tag for pmr-AA types.
472
473 // TYPES
475};
476
477 // =================
478 // struct AAModelBsl
479 // =================
480
481/// Model tag for bsl-AA types.
483
484 // TYPES
486};
487
488 // ====================
489 // struct AAModelLegacy
490 // ====================
491
492/// Model tag for legacy-AA types.
494
495 // TYPES
497};
498
499 // =================
500 // struct AAModelStl
501 // =================
502
503/// Model tag for stl-AA types.
505
506 // TYPES
508};
509
510 // =======================
511 // struct template AAModel
512 // =======================
513
514/// Metafunction that yields (is derived from) a model tag type that
515/// indicates the AA model preferred for the specified type -- one of
516/// `AAModelPmr`, `AAModelBsl`, `AAModelLegacy`, `AAModelStl`, or
517/// `AAModelNone`. If `TYPE` supports more than one of AA models, then the
518/// result is the first in the preceding list that is supported.
519template <class TYPE>
520struct AAModel : AAModel_Imp<TYPE,
521 AAModelPmr,
522 AAModelBsl,
523 AAModelLegacy,
524 AAModelStl,
525 AAModelNone>::type {
526};
527
528 // =================================
529 // struct template AAModeIsSupported
530 // =================================
531
532/// Predicate metafunction that determines if the specified `TYPE` supports
533/// the specified `MODEL` AA model. It yields (i.e., is derived from)
534/// `bsl:true_type` if type `TYPE` supports AA model `MODEL`; otherwise it
535/// yields `false_type`. `MODEL` Must be one of `AAModelNone`,
536/// `AAModelLegacy`, `AAModelBsl`, `AAModelPmr`, or `AAModelStl`. This
537/// metafunction can yield `true_type` for more than one type `MODEL` type,
538/// e.g., it will yield `true_type` if `TYPE` is **bsl-AA**, and `MODEL` is
539/// either `AAModelBsl` or `AAModelLegacy`, since `TYPE` can be constructed
540/// with either allocator type.
541template <class TYPE, class MODEL>
544
545/// Specialization of `AAModelIsSupported` for `MODEL == AAModelNone`,
546/// always yielding `true_type`.
547template <class TYPE>
550
551/// Specialization of `AAModelIsSupported` for `MODEL == AAModelPmr`,
552/// yielding `true_type` if `TYPE::allocator_type` exists and is convertible
553/// from `bsl::polymorphic_allocator<char>`.
554template <class TYPE>
557 bsl::uses_allocator<TYPE, bsl::polymorphic_allocator<char> >::value> {
558};
559
560/// Specialization of `AAModelIsSupported` for `MODEL == AAModelBsl`,
561/// yielding `true_type` if `TYPE::allocator_type` exists and is convertible
562/// from `bsl::allocator<char>`.
563template <class TYPE>
566 bsl::uses_allocator<TYPE, bsl::allocator<char> >::value ||
567 AAModelIsSupported<TYPE, AAModelPmr>::value> {
568};
569
570/// Specialization of `AAModelIsSupported` for `MODEL == AAModelStl`,
571/// yielding `true_type` if `TYPE` can use `bslma::Allocator *` as its
572/// memory resource. Specifically, it is true if `UsesBslmaAllocator<TYPE>`
573/// is true or if `TYPE::allocator_type` exists and is convertible from
574/// `bslma::Allocator *`.
575template <class TYPE>
578 UsesBslmaAllocator<TYPE>::value ||
579 AAModelIsSupported<TYPE, AAModelBsl>::value> {
580};
581
582/// Specialization of `AAModelIsSupported` for `MODEL == AAModelStl`,
583/// yielding `true_type` if `TYPE::allocator_type` exists; otherwise,
584/// yielding `false_type` unless `AAModelIsSupported<TYPE, AAModelBsl>` is
585/// true. The latter condition exists so that **bsl-AA** always implies
586/// **stl-AA** even if `AAModelIsSupported<TYPE, AAModelBsl>` is explicitly
587/// specialized to true for a type that does not have an `allocator_type`
588/// member.
589template <class TYPE>
592 HasAllocatorType<TYPE>::value ||
593 AAModelIsSupported<TYPE, AAModelBsl>::value>
594{
595};
596
597// ============================================================================
598// TEMPLATE AND INLINE FUNCTION IMPLEMENTATIONS
599// ============================================================================
600
601 // ===========================
602 // struct template AAModel_Imp
603 // ===========================
604
605/// Implementation of `bslma::AAModel` metafunction. Tries each of the
606/// specified `MODEL1` to `MODEL5` template arguments and sets the member
607/// `typedef`, `type`, to the first model that is supported by the
608/// specified `TYPE`. All arguments except the first are defaulted in the
609/// forward declaration. Note that `type` will not be defined if `TYPE`
610/// doesn't support at least one of the passed-in models.
611template <class TYPE,
612 class MODEL1,
613 class MODEL2,
614 class MODEL3,
615 class MODEL4,
616 class MODEL5>
618
619 // Implementation note 1: this metafunction could have been implemented
620 // slightly more compactly using variadic templates, but it seemed
621 // unnecessary to involve the C++03 variadic emulation for a fixed-length
622 // pack of 5 parameters.
623 //
624 // Implementation note 2: To avoid infinite compile-time recursion, do not
625 // instantiate the 'type' member of 'AAModel_Imp' within the
626 // 'bsl::conditional', below. If the condition is 'true', the first
627 // '::type' after the 'conditional' selects the 'AAModel_Imp'
628 // specialization whereas the second '::type' yields the recursive
629 // application of the metafunction; there is no recursion if the condition
630 // is 'false'. This idiom is the compile-time equivalent of having a
631 // conditional expression that returns a pointer-to-function that, only
632 // when invoked, could yield a recursive call.
633
634 // TYPES
635
636 /// One of `MODEL1` to `MODEL5`, indicating the model supported by
637 /// `TYPE`. If multiple models are supported, then the first supported
638 /// one in the template argument list is used.
639 typedef typename bsl::conditional<
641 MODEL1,
644};
645
646/// Partial specialization of `AAModel_Imp` for when none of the supplied
647/// models is supported (should never happen). The nested `type` alias does
648/// not exist in this specialization.
649template <class TYPE>
650struct AAModel_Imp<TYPE, void, void, void, void, void> {
651};
652
653} // close package namespace
654
655
656#endif // ! defined(INCLUDED_BSLMA_AAMODEL)
657
658// ----------------------------------------------------------------------------
659// Copyright 2022 Bloomberg Finance L.P.
660//
661// Licensed under the Apache License, Version 2.0 (the "License");
662// you may not use this file except in compliance with the License.
663// You may obtain a copy of the License at
664//
665// http://www.apache.org/licenses/LICENSE-2.0
666//
667// Unless required by applicable law or agreed to in writing, software
668// distributed under the License is distributed on an "AS IS" BASIS,
669// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
670// See the License for the specific language governing permissions and
671// limitations under the License.
672// ----------------------------- END-OF-FILE ----------------------------------
673
674/** @} */
675/** @} */
676/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balxml_encoderoptions.h:68
Definition bslmf_conditional.h:120
Definition bslmf_integralconstant.h:244
integral_constant type
Definition bslmf_integralconstant.h:255
Model tag for bsl-AA types.
Definition bslma_aamodel.h:482
AAModelBsl type
Definition bslma_aamodel.h:485
Definition bslma_aamodel.h:542
Model tag for legacy-AA types.
Definition bslma_aamodel.h:493
AAModelLegacy type
Definition bslma_aamodel.h:496
Model tag for non-AA types.
Definition bslma_aamodel.h:460
AAModelNone type
Definition bslma_aamodel.h:463
Model tag for pmr-AA types.
Definition bslma_aamodel.h:471
AAModelPmr type
Definition bslma_aamodel.h:474
Model tag for stl-AA types.
Definition bslma_aamodel.h:504
AAModelStl type
Definition bslma_aamodel.h:507
Definition bslma_aamodel.h:617
bsl::conditional< AAModelIsSupported< TYPE, MODEL1 >::value, MODEL1, AAModel_Imp< TYPE, MODEL2, MODEL3, MODEL4, MODEL5 > >::type::type type
Definition bslma_aamodel.h:643
Definition bslma_aamodel.h:525