BDE 4.14.0 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/// Note that this metafunction produces the same type as
167/// `bsl::allocator_traits<TYPE>::size_type`, but avoids a dependency on
168/// @ref bslma_allocatortraits and is guaranteed to compile even if `TYPE` is
169/// not an allocator type.
170template <class TYPE, class = void>
172{
173
174 typedef std::size_t type;
175};
176
177/// This specialization is selected when `TYPE` has a nested `size_type`.
178template <class TYPE>
180 TYPE,
181 typename bslmf::VoidType<typename TYPE::size_type>::type> {
182
183 typedef typename TYPE::size_type type;
184};
185
186 // ==============================
187 // struct template IsStdAllocator
188 // ==============================
189
190/// Metafunction to determine whether the specified template parameter
191/// `TYPE` meets the minimum requirements for a C++11 allocator.
192/// Specifically, this `struct` is derived from `true_type` if `TYPE` has a
193/// nested `value_type` and supports the operation `a.allocate(bytes)`,
194/// where `a` has type `TYPE` and `bytes` has type
195/// `allocator_traits<TYPE>::size_type`; otherwise it is derived from
196/// `false_type`.
197template <class TYPE>
199 : IsStdAllocator_Imp<TYPE,
200 typename IsStdAllocator_SizeType<TYPE>::type>::type
201{
202};
203
204#ifdef BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES
205/// This template variable represents the result value of the
206/// `bslma::IsStdAllocator` meta-function.
207template <class TYPE>
209constexpr bool IsStdAllocator_v = IsStdAllocator<TYPE>::value;
210#endif
211
212/// Specialization for lvalue reference types.
213template <class TYPE>
215};
216
217#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
218/// Specialization for rvalue reference types.
219template <class TYPE>
220struct IsStdAllocator<TYPE&&> : bsl::false_type {
221};
222#endif
223
224/// Specialization for `std::allocator`.
225template <class TYPE>
226struct IsStdAllocator<std::allocator<TYPE> > : bsl::true_type {
227};
228
229/// `std::allocator<void>` is not an allocator type, even though all other
230/// specializations are allocator types.
231template <>
232struct IsStdAllocator<std::allocator<void> > : bsl::false_type {
233};
234
235// ============================================================================
236// TEMPLATE IMPLEMENTATIONS
237// ============================================================================
238
239 // ----------------------------------
240 // struct template IsStdAllocator_Imp
241 // ----------------------------------
242
243#ifdef BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
244
245/// This C++11 primary template yields `false_type`. It is selected when
246/// either `TYPE::value_type` does not exists or `a.allocate(bytes)` is
247/// ill-formed, where `a` has type `TYPE` and `bytes` has type `SIZE_T`.
248template <class TYPE, class SIZE_T, class>
250
251 // If this assert fails, it means that 'bslma::IsStdAllocator' is declared
252 // as a nested trait within 'TYPE' but 'TYPE' does not meet the C++11
253 // allocator requirements.
255};
256
257/// This C++11 specialization yields `true_type` and is selected when
258/// `TYPE::value_type` exists and `a.allocate(bytes)` is well-formed, where
259/// `a` has type `TYPE` and `bytes` has type `SIZE_T`.
260template <class TYPE, class SIZE_T>
261struct IsStdAllocator_Imp<
262 TYPE,
263 SIZE_T,
264 bsl::void_t<typename TYPE::value_type,
265 decltype(std::declval<TYPE&>().allocate(SIZE_T()))> >
266 : public bsl::true_type {
267
268#ifndef BSLMA_ISALLOCATOR_IGNORE_CPP03_COMPATIBILITY
269 // If this assert fails, it means that 'TYPE' meets the C++11 allocator
270 // requirements but cannot be detected as being an allocator using a C++03
271 // compiler. Specifically, 'bslma::IsStdAllocator' is neither specialized
272 // for 'TYPE' nor declared as a nested trait within 'TYPE'. Although
273 // explicitly declaring this trait would not be necessary for a C++11 or
274 // later compiler, this assertion prevents portability errors whereby real
275 // allocator types that would not be recognized as such in C++03. To
276 // suppress this compatibility check, '#define'
277 // 'BSLMA_ISALLOCATOR_IGNORE_CPP03_COMPATIBILITY' before the '#include' for
278 // this header.
280#endif
281};
282
283#else // if ! defined(BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE)
284
285/// This C++03 primary template metafunction is derived from `false_type`.
286/// It is selected when the specified template paramter `TYPE` does not
287/// declare itself to be an allocator, i.e., when
288/// `bslmf::DetectNestedTrait<TYPE, IsStdAllocator>::value` is `false`.
289template <class TYPE, class SIZE_T, class>
292
293/// This C++03 specialization is derived from `true_type`. It is selected
294/// when the specified template parameter `TYPE` is a class that declares
295/// the nested `IsStdAllocator` trait. This specialization contains
296/// compile-time correctness checks to ensure that `TYPE` really does have
297/// `value_type` and `allocator()` members.
298template <class TYPE, class SIZE_T>
300 TYPE,
301 SIZE_T,
302 typename bsl::enable_if<
303 bslmf::DetectNestedTrait<TYPE, IsStdAllocator>::value>::type
304 >
306
307 private:
308 // TYPES
309 template <class T> struct check { };
310
311 // NOT DEFINED
312 static TYPE& allocObj;
313
314 // COMPILE-TIME CORRECTNESS CHECK:
315 // If 'TYPE' is declared as being an allocator, the following assertions
316 // will fail even to compile unless 'TYPE' also meets the minimum
317 // requirements for a C++11 allocator. These tests prevent non-allocators
318 // from being declared as allocators.
319 BSLMF_ASSERT(sizeof(check<typename TYPE::value_type>) > 0);
320 BSLMF_ASSERT(sizeof(allocObj.allocate(SIZE_T())) > 0);
321};
322
323#endif // ! BSLS_COMPILERFEATURES_SUPPORT_DECLTYPE
324
325} // close package namespace
326
327
328// For backwards compatibility:
329namespace bsl {
330
331using BloombergLP::bslma::IsStdAllocator;
332
333#ifdef BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES
334using BloombergLP::bslma::IsStdAllocator_v;
335#endif
336
337} // close namespace bsl
338
339#endif // INCLUDED_BSLMA_ISSTDALLOCATOR
340
341// ----------------------------------------------------------------------------
342// Copyright 2021 Bloomberg Finance L.P.
343//
344// Licensed under the Apache License, Version 2.0 (the "License");
345// you may not use this file except in compliance with the License.
346// You may obtain a copy of the License at
347//
348// http://www.apache.org/licenses/LICENSE-2.0
349//
350// Unless required by applicable law or agreed to in writing, software
351// distributed under the License is distributed on an "AS IS" BASIS,
352// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
353// See the License for the specific language governing permissions and
354// limitations under the License.
355// ----------------------------- END-OF-FILE ----------------------------------
356
357/** @} */
358/** @} */
359/** @} */
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_INLINE_VARIABLE
Definition bsls_keyword.h:623
Definition bdlb_printmethods.h:283
Definition balxml_encoderoptions.h:68
Definition bdlbb_blob.h:576
Definition bdldfp_decimal.h:5188
Definition bslmf_integralconstant.h:244
Definition bslma_isstdallocator.h:290
Definition bslma_isstdallocator.h:172
std::size_t type
Definition bslma_isstdallocator.h:174
Definition bslma_isstdallocator.h:201
Definition bslmf_detectnestedtrait.h:464