BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslma_isstdallocator.h
Go to the documentation of this file.
1/// @file bslma_isstdallocator.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_isstdallocator.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_ISSTDALLOCATOR
9#define INCLUDED_BSLMA_ISSTDALLOCATOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_isstdallocator bslma_isstdallocator
15/// @brief Provide a compile-time check for determining allocator types.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_isstdallocator
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_isstdallocator-purpose"> Purpose</a>
25/// * <a href="#bslma_isstdallocator-classes"> Classes </a>
26/// * <a href="#bslma_isstdallocator-description"> Description </a>
27/// * <a href="#bslma_isstdallocator-usage"> Usage </a>
28/// * <a href="#bslma_isstdallocator-example-1-verify-if-a-class-meets-the-requirements-for-an-allocator"> Example 1: Verify if a class meets the requirements for an allocator. </a>
29///
30/// # Purpose {#bslma_isstdallocator-purpose}
31/// Provide a compile-time check for determining allocator types.
32///
33/// # Classes {#bslma_isstdallocator-classes}
34///
35/// - bslma::IsStdAllocator: meta-function to determine if a type is an allocator
36/// - bslma::IsStdAllocator_v: Boolean result of `bslma::IsStdAllocator`
37///
38/// # Description {#bslma_isstdallocator-description}
39/// This component defines a meta-function, `bslma::IsStdAllocator`
40/// and a variable template, `bslma::IsStdAllocator_v`, that represents the
41/// result value of the `bslma::IsStdAllocator` meta-function.
42///
43/// `bslma::IsStdAllocator` is used to determine if a type meets the
44/// requirements for an allocator, as specified in
45/// [container.requirements.general]. Note that there is no `is_allocator`
46/// trait specified in the C++ standard, even though every C++ implementation
47/// has a private equivalent.
48///
49/// In C++03, it is impossible to automatically detect conformance to the
50/// allocator requirements, owing to limitations in SFINAE capabilities; even
51/// elaborate detection metaprogramming will break if a type has a private
52/// `allocate` method. Therefore, a portable allocator type, *some-alloc*, must
53/// have `bslma::IsStdAllocator<some-alloc>` specified directly. There are two
54/// ways to specify this trait:
55///
56/// 1. Specialize `IsStdAllocator<some-alloc>` to derive from `bsl::true_type`
57/// in namespace `BloombergLP::bslma`.
58/// 2. Add 'BSLMF_NESTED_TRAIT_DECLARATION(some-alloc,
59/// bslma::IsStdAllocator)' within the public portion of the class definition
60/// for *some-alloc*.
61///
62/// The first option will bypass any automatic-detection metalogic. The second
63/// option is preferred because it will be checked for correctness -- failing to
64/// compile if the allocator is missing a critical member.
65///
66/// In C++11 and later, the `bslma::IsStdAllocator` trait is detected
67/// automatically: for any type `A` having a `value_type` and `allocate` method
68/// that meet the allocator requirements, `bslma::IsStdAllocator<A>::value` will
69/// be `true`. However, to prevent inadvertantly declaring an allocator that is
70/// not detected in a C++03 build, using this trait in C++11 or later build will
71/// yield a compilation error if it is detected that a type is an allocator does
72/// not have `IsStdAllocator` explicitly specified. The simplest way to avoid
73/// that error is to specify `IsStdAllocator` deliberately for *every*
74/// allocator, as described above. Alternatively, defining the
75/// `BSLMA_ISALLOCATOR_IGNORE_CPP03_COMPATIBILITY` macro will suppress the error
76/// in C++11 and later builds, defering to automatic allocator detection.
77///
78/// If C++14 variable templates and constexpr variables are supported, the
79/// variable template `IsStdAllocator_v` is defined to be the value
80/// `IsStdAllocator<T>::value`. If C++17 inline variables are supported, it is
81/// inline.
82///
83/// ## Usage {#bslma_isstdallocator-usage}
84///
85///
86/// This section shows the intended use of this component.
87///
88/// ### Example 1: Verify if a class meets the requirements for an allocator. {#bslma_isstdallocator-example-1-verify-if-a-class-meets-the-requirements-for-an-allocator}
89///
90///
91/// Suppose that we want to assert whether a set of types meet the requirements
92/// for allocators.
93///
94/// First, we create a struct type `MyAllocator`:
95/// @code
96/// struct MyAllocator
97/// {
98/// BSLMF_NESTED_TRAIT_DECLARATION(MyAllocator, bslma::IsStdAllocator);
99/// typedef int value_type;
100///
101/// /// Allocate some memory for use by the caller.
102/// int *allocate(size_t);
103/// };
104/// @endcode
105/// Now, we instantiate the `bslma::IsStdAllocator` template for both a type
106/// that does not meet the allocator requirements and the defined type
107/// `MyClass`, that does, asserting the `value` static data member of each
108/// instantiation.
109/// @code
110/// int main()
111/// {
112/// assert(false == bslma::IsStdAllocator<int>::value);
113/// assert(true == bslma::IsStdAllocator<MyAllocator>::value);
114/// @endcode
115/// Note that if the current compiler supports C++14 variable templates then we
116/// can re-write the snippet of code above using the `bslma::IsStdAllocator_v`
117/// variable:
118/// @code
119/// #ifdef BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES
120/// assert(false == bslma::IsStdAllocator_v<int>);
121/// assert(true == bslma::IsStdAllocator_v<MyAllocator>);
122/// #endif
123/// }
124/// @endcode
125/// @}
126/** @} */
127/** @} */
128
129/** @addtogroup bsl
130 * @{
131 */
132/** @addtogroup bslma
133 * @{
134 */
135/** @addtogroup bslma_isstdallocator
136 * @{
137 */
138
139#include <bslscm_version.h>
140
141#include <bslmf_assert.h>
143#include <bslmf_enableif.h>
145#include <bslmf_voidtype.h>
146
148#include <bsls_keyword.h>
149
150#include <cstddef> // 'std::size_t'
151#include <memory> // 'std::allocator'
152
153
154namespace bslma {
155
156// FORWARD DECLARATIONS
157template <class TYPE, class SIZE_T, class = void> struct IsStdAllocator_Imp;
158
159 // =======================================
160 // struct template IsStdAllocator_SizeType
161 // =======================================
162
163/// This component-private metafunction determines the appopriate size type
164/// for a specified template parameter `TYPE`. The nested `type` typedef is
165/// `TYPE::size_type` if such a type exists and `std::size_t` otherwise.
166///
167/// \note Note that this metafunction produces the same type as
168/// `bsl::allocator_traits<TYPE>::size_type`, but avoids a dependency on
169/// @ref bslma_allocatortraits and is guaranteed to compile even if `TYPE` is
170/// not an allocator type.
171template <class TYPE, class = void>
173{
174
175 typedef std::size_t type;
176};
177
178/// This specialization is selected when `TYPE` has a nested `size_type`.
179template <class TYPE>
181 TYPE,
182 typename bslmf::VoidType<typename TYPE::size_type>::type> {
183
184 typedef typename TYPE::size_type type;
185};
186
187 // ==============================
188 // struct template IsStdAllocator
189 // ==============================
190
191/// Metafunction to determine whether the specified template parameter
192/// `TYPE` meets the minimum requirements for a C++11 allocator.
193/// Specifically, this `struct` is derived from `true_type` if `TYPE` has a
194/// nested `value_type` and supports the operation `a.allocate(bytes)`,
195/// where `a` has type `TYPE` and `bytes` has type
196/// `allocator_traits<TYPE>::size_type`; otherwise it is derived from
197/// `false_type`.
198template <class TYPE>
200 : IsStdAllocator_Imp<TYPE,
201 typename IsStdAllocator_SizeType<TYPE>::type>::type
202{
203};
204
205#ifdef BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES
206/// This template variable represents the result value of the
207/// `bslma::IsStdAllocator` meta-function.
208template <class TYPE>
210constexpr bool IsStdAllocator_v = IsStdAllocator<TYPE>::value;
211#endif
212
213/// Specialization for lvalue reference types.
214template <class TYPE>
216};
217
218#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
219/// Specialization for rvalue reference types.
220template <class TYPE>
221struct IsStdAllocator<TYPE&&> : bsl::false_type {
222};
223#endif
224
225/// Specialization for `std::allocator`.
226template <class TYPE>
227struct IsStdAllocator<std::allocator<TYPE> > : bsl::true_type {
228};
229
230/// `std::allocator<void>` is not an allocator type, even though all other
231/// specializations are allocator types.
232template <>
233struct IsStdAllocator<std::allocator<void> > : bsl::false_type {
234};
235
236// ============================================================================
237// TEMPLATE IMPLEMENTATIONS
238// ============================================================================
239
240 // ----------------------------------
241 // struct template IsStdAllocator_Imp
242 // ----------------------------------
243
244#ifdef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
245
246/// This C++11 primary template yields `false_type`. It is selected when
247/// either `TYPE::value_type` does not exists or `a.allocate(bytes)` is
248/// ill-formed, where `a` has type `TYPE` and `bytes` has type `SIZE_T`.
249template <class TYPE, class SIZE_T, class>
251
252 // If this assert fails, it means that 'bslma::IsStdAllocator' is declared
253 // as a nested trait within 'TYPE' but 'TYPE' does not meet the C++11
254 // allocator requirements.
256};
257
258/// This C++11 specialization yields `true_type` and is selected when
259/// `TYPE::value_type` exists and `a.allocate(bytes)` is well-formed, where
260/// `a` has type `TYPE` and `bytes` has type `SIZE_T`.
261template <class TYPE, class SIZE_T>
262struct IsStdAllocator_Imp<
263 TYPE,
264 SIZE_T,
265 bsl::void_t<typename TYPE::value_type,
266 decltype(std::declval<TYPE&>().allocate(SIZE_T()))> >
267 : public bsl::true_type {
268
269#ifndef BSLMA_ISALLOCATOR_IGNORE_CPP03_COMPATIBILITY
270 // If this assert fails, it means that 'TYPE' meets the C++11 allocator
271 // requirements but cannot be detected as being an allocator using a C++03
272 // compiler. Specifically, 'bslma::IsStdAllocator' is neither specialized
273 // for 'TYPE' nor declared as a nested trait within 'TYPE'. Although
274 // explicitly declaring this trait would not be necessary for a C++11 or
275 // later compiler, this assertion prevents portability errors whereby real
276 // allocator types that would not be recognized as such in C++03. To
277 // suppress this compatibility check, '#define'
278 // 'BSLMA_ISALLOCATOR_IGNORE_CPP03_COMPATIBILITY' before the '#include' for
279 // this header.
281#endif
282};
283
284#else // if ! defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)
285
286/// This C++03 primary template metafunction is derived from `false_type`.
287/// It is selected when the specified template paramter `TYPE` does not
288/// declare itself to be an allocator, i.e., when
289/// `bslmf::DetectNestedTrait<TYPE, IsStdAllocator>::value` is `false`.
290template <class TYPE, class SIZE_T, class>
293
294/// This C++03 specialization is derived from `true_type`. It is selected
295/// when the specified template parameter `TYPE` is a class that declares
296/// the nested `IsStdAllocator` trait. This specialization contains
297/// compile-time correctness checks to ensure that `TYPE` really does have
298/// `value_type` and `allocator()` members.
299template <class TYPE, class SIZE_T>
301 TYPE,
302 SIZE_T,
303 typename bsl::enable_if<
304 bslmf::DetectNestedTrait<TYPE, IsStdAllocator>::value>::type
305 >
307
308 private:
309 // TYPES
310 template <class T> struct check { };
311
312 // NOT DEFINED
313 static TYPE& allocObj;
314
315 // COMPILE-TIME CORRECTNESS CHECK:
316 // If 'TYPE' is declared as being an allocator, the following assertions
317 // will fail even to compile unless 'TYPE' also meets the minimum
318 // requirements for a C++11 allocator. These tests prevent non-allocators
319 // from being declared as allocators.
320 BSLMF_ASSERT(sizeof(check<typename TYPE::value_type>) > 0);
321 BSLMF_ASSERT(sizeof(allocObj.allocate(SIZE_T())) > 0);
322};
323
324#endif // ! BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
325
326} // close package namespace
327
328
329// For backwards compatibility:
330namespace bsl {
331
332using BloombergLP::bslma::IsStdAllocator;
333
334#ifdef BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES
335using BloombergLP::bslma::IsStdAllocator_v;
336#endif
337
338} // close namespace bsl
339
340#endif // INCLUDED_BSLMA_ISSTDALLOCATOR
341
342// ----------------------------------------------------------------------------
343// Copyright 2021 Bloomberg Finance L.P.
344//
345// Licensed under the Apache License, Version 2.0 (the "License");
346// you may not use this file except in compliance with the License.
347// You may obtain a copy of the License at
348//
349// http://www.apache.org/licenses/LICENSE-2.0
350//
351// Unless required by applicable law or agreed to in writing, software
352// distributed under the License is distributed on an "AS IS" BASIS,
353// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
354// See the License for the specific language governing permissions and
355// limitations under the License.
356// ----------------------------- END-OF-FILE ----------------------------------
357
358/** @} */
359/** @} */
360/** @} */
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_INLINE_VARIABLE
Definition bsls_keyword.h:665
Definition bdlat_valuetypefunctions.h:939
Definition baljsn_encoder_testtypes.h:76
Definition bdlbb_blob.h:579
Definition bdldfp_decimal.h:5549
Definition bslmf_integralconstant.h:261
Definition bslma_isstdallocator.h:291
Definition bslma_isstdallocator.h:173
std::size_t type
Definition bslma_isstdallocator.h:175
Definition bslma_isstdallocator.h:202
Definition bslmf_detectnestedtrait.h:467