BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslmf_isempty.h
Go to the documentation of this file.
1/// @file bslmf_isempty.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmf_isempty.h -*-C++-*-
8#ifndef INCLUDED_BSLMF_ISEMPTY
9#define INCLUDED_BSLMF_ISEMPTY
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmf_isempty bslmf_isempty
15/// @brief Provide a compile-time check for detecting an empty class type.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmf
19/// @{
20/// @addtogroup bslmf_isempty
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmf_isempty-purpose"> Purpose</a>
25/// * <a href="#bslmf_isempty-classes"> Classes </a>
26/// * <a href="#bslmf_isempty-description"> Description </a>
27/// * <a href="#bslmf_isempty-usage"> Usage </a>
28/// * <a href="#bslmf_isempty-example-1-compute-storage-requirements-for-a-type"> Example 1: Compute Storage Requirements for a Type </a>
29///
30/// # Purpose {#bslmf_isempty-purpose}
31/// Provide a compile-time check for detecting an empty class type.
32///
33/// # Classes {#bslmf_isempty-classes}
34///
35/// - bsl::is_empty: standard meta-function for detecting empty classes
36/// - bsl::is_empty_v: the result value of the `bsl::is_empty` meta-function
37///
38/// @see bslmf_isclass.h
39///
40/// # Description {#bslmf_isempty-description}
41/// This component defines a meta-function, `bsl::is_empty` and a
42/// template variable `bsl::is_empty_v`, that represents the result value of the
43/// `bsl::is_empty` meta-function, which may be used to determine whether a type
44/// is a `class` or `struct` with no non-static data members other than
45/// bit-fields of length 0, no virtual member functions, no virtual base
46/// classes, and no base class `B` for which `is_empty<B>::value` is `false`.
47/// This meta-function conforms to the definition of the C++11 standard
48/// `is_empty` meta-function in section [meta.unary.prop].
49///
50/// An empty class type type is *usually* stateless and, can be "stored" in a
51/// zero-length memory region. (Hypothetically, an empty object can hold state
52/// by means a global address-to-state map, but such a design is rare and is
53/// discouraged.) When a class inherits from an empty type, the compiler is
54/// expected to optimize away the storage requirements of the empty base class.
55/// This optimization is known as the "Empty Base Optimization" or "EBO".
56///
57/// Note that the template variable `is_empty_v` is defined in the C++17
58/// standard as an inline variable. If the current compiler supports the inline
59/// variable C++17 compiler feature, `bsl::is_empty_v` is defined as an
60/// `inline constexpr bool` variable. Otherwise, if the compiler supports the
61/// variable templates C++14 compiler feature, `bsl::is_empty_v` is defined as a
62/// non-inline `constexpr bool` variable. See
63/// `BSLS_COMPILERFEATURES_SUPPORT_INLINE_VARIABLES` and
64/// `BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES` macros in
65/// bsls_compilerfeatures component for details.
66///
67/// ## Usage {#bslmf_isempty-usage}
68///
69///
70/// In this section we show intended use of this component.
71///
72/// ### Example 1: Compute Storage Requirements for a Type {#bslmf_isempty-example-1-compute-storage-requirements-for-a-type}
73///
74///
75/// Suppose we wish to create a generic function that will allocate a record
76/// comprising a value of specified `t_TYPE` and a description in the form of a
77/// null-terminated character string. First, we declare the function prototype:
78/// @code
79/// template <class t_TYPE>
80/// void *makeRecord(const t_TYPE& value, const char* description);
81/// @endcode
82/// Next, we implement the function so that the copy of `value` takes up no
83/// space if `t_TYPE` is an empty class. We manage this by computing a zero
84/// storage requirement if `is_empty<t_TYPE>::value` is true:
85/// @code
86/// #include <cstring>
87/// #include <new>
88///
89/// template <class t_TYPE>
90/// void *makeRecord(const t_TYPE& value, const char* description)
91/// {
92/// // 'ValueSize' is computed at compile time.
93/// static const std::size_t ValueSize = bsl::is_empty<t_TYPE>::value ?
94/// 0 : sizeof(t_TYPE);
95///
96/// // Allocate memory for value and description
97/// const std::size_t MemSize = ValueSize + std::strlen(description) + 1;
98/// void *mem = ::operator new(MemSize);
99///
100/// // Construct copy of value at front of allocated memory
101/// ::new(mem) t_TYPE(value);
102///
103/// // Copy description into space following value.
104/// std::strcpy(static_cast<char*>(mem) + ValueSize, description);
105///
106/// return mem;
107/// }
108/// @endcode
109/// Finally, we use `makeRecord` with both an empty and non-empty value type:
110/// @code
111/// struct EmptyMarker { };
112///
113/// int main()
114/// {
115/// void *record1 = makeRecord(9999, "four nines");
116/// // Value takes 'sizeof(int)' bytes at front of record.
117/// assert(9999 == *static_cast<int*>(record1));
118/// assert(0 == std::strcmp(static_cast<char*>(record1) + sizeof(int),
119/// "four nines"));
120///
121/// void *record2 = makeRecord(EmptyMarker(), "Empty");
122/// // Value takes no space at front of record.
123/// assert(0 == std::strcmp(static_cast<char*>(record2), "Empty"));
124///
125/// ::operator delete(record1);
126/// ::operator delete(record2);
127///
128/// return 0;
129/// }
130/// @endcode
131/// @}
132/** @} */
133/** @} */
134
135/** @addtogroup bsl
136 * @{
137 */
138/** @addtogroup bslmf
139 * @{
140 */
141/** @addtogroup bslmf_isempty
142 * @{
143 */
144
145#include <bslscm_version.h>
146
148#include <bslmf_voidtype.h>
149
151#include <bsls_keyword.h>
152
153#if defined(BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER)
154# include <type_traits>
155#endif // BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER
156
157#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
158#include <bsls_nativestd.h>
159#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
160
161#if defined(BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER)
162# define BSLMF_ISEMPTY_USE_NATIVE_TRAIT 1
163#endif
164
165#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
166#include <bslmf_isclass.h>
167#endif
168
169namespace bsl {
170
171 // ===============
172 // struct is_empty
173 // ===============
174
175/// This `struct` is a meta-function to determine whether the (template
176/// parameter) `t_TYPE` is an empty class type. This `struct` derives from
177/// `bsl::true_type` if the `t_TYPE` is empty, and from `bsl::false_type`
178/// otherwise. This meta-function has the same syntax as the `is_empty`
179/// meta-function defined in the C++11 standard [meta.unary.prop]; on C++03
180/// platforms, however, this meta-function defaults to `true_type` if
181/// `t_TYPE` is a `class` or `struct` with no non-static data members other
182/// than bit-fields of length 0, no virtual member functions, no virtual
183/// base classes, and no base class `B` for which `is_empty<B>::value` is `false`; otherwise `is_empty` defaults to `false_type`.
184///
185/// \note Note that this
186/// meta-function will fail to compile for a union that is the same size as
187/// an empty class in C++03.
188template <class t_TYPE>
189struct is_empty;
190
191} // close namespace bsl
192
193// ============================================================================
194// CLASS TEMPLATE DEFINITIONS
195// ============================================================================
196namespace bsl {
197#if defined(BSLMF_ISEMPTY_USE_NATIVE_TRAIT)
198
199 // =======================
200 // struct is_empty (C++11)
201 // =======================
202
203/// This specification defers to the native trait on supported C++11
204/// compilers.
205template <class t_TYPE>
206struct is_empty
207: bsl::integral_constant<bool, ::std::is_empty<t_TYPE>::value> {
208};
209
210#ifdef BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES
211/// This template variable represents the result value of the
212/// `bsl::is_empty` meta-function.
213template <class t_TYPE>
214BSLS_KEYWORD_INLINE_VARIABLE constexpr bool is_empty_v =
216#endif
217
218#else
219
220 // ====================
221 // struct Is_Empty_Size
222 // ====================
223
224/// Private class: do not use outside of @ref bslmf_isempty component. This
225/// component-private class is an example of an empty type, that can be used
226/// to calculate the likely size of an empty type on the current platform.
227/// As the inheritance-based technique used below disallows unions with a
228/// hard error, rather than a SFINAE-friendly failure, it is important to
229/// avoid instantiating the `Imp` test unless there is a real chance that
230/// the type might be empty. While we cannot protect against testing small
231/// unions, we can rule out the more common cases where at least one union
232/// member has more than the smallest permissible size on the current ABI.
233///
234/// See @ref bslmf_isempty
236};
237
238 // =========================
239 // struct Is_Empty_Class_Imp
240 // =========================
241
242/// Private class: do not use outside of @ref bslmf_isempty component. This
243/// meta-function derives from `false_type` unless (the template parameter)
244/// `t_TYPE` is exactly the same size as a known empty type, in which case
245/// the following partial specialization is chosen. This test filters out
246/// the majority of problems with `union` types that are classes, and would
247/// produce a hard, non-SFINAEable error trying to a create a derived class
248/// to compare size in the next test.
249template <class t_TYPE,
250 bool IS_CLASS = sizeof(t_TYPE) == sizeof(Is_Empty_Size)>
253
254/// Private class: do not use outside of @ref bslmf_isempty component.
255/// Implementation of `bsl::is_empty` for class types that are small enough
256/// that they might be an empty class.
257template <class t_TYPE>
258struct Is_Empty_Class_Imp<t_TYPE, true> {
259
260 private:
261 /// This `struct` derives from the template parameter `t_TYPE` from the
262 /// enclosing class template, and will have the same size as an `int` if
263 /// `t_TYPE` is an empty class, and a larger size otherwise.
264 struct Derived : t_TYPE {
265
266 Derived(); // Declared but not defined
267 Derived(const Derived&); // Declared but not defined
268 ~Derived(); // Declared but not defined
269
270 int d_data; // 'Derived' is not empty
271 };
272
273 public:
274 /// `true_type` if (the template parameter) `t_TYPE` is an empty class,
275 /// and `false_type` otherwise.
276 typedef integral_constant<bool, sizeof(Derived) == sizeof(int)> type;
277};
278
279 // ===================
280 // struct Is_Empty_Imp
281 // ===================
282
283/// Private class: do not use outside of @ref bslmf_isempty component. This
284/// meta-function provides an initial dispatch that always derives from
285/// `false_type` unless the template parameter `t_TYPE` is a class type, as
286/// only class types can be empty. The following partial specialization
287/// forwards all class types to a final test. This two-phase dispatch is
288/// necessary as some types, such as `void` and function types, cannot be
289/// passed to a `sizeof` operator that is used to implement the next stage
290/// of matching.
291template <class t_TYPE, class = void>
293};
294
295/// Private class: do not use outside of @ref bslmf_isempty component.
296/// Implementation of `bsl::is_empty`. This partial specialization derives
297/// from the nested `type` member of the `Is_Empty_Class_Imp` meta-function,
298/// which must be `true_type` if (the template parameter) `t_TYPE` is an
299/// empty class, and `false_type` otherwise.
300template <class t_TYPE>
301struct Is_Empty_Imp<t_TYPE, BSLMF_VOIDTYPE(int t_TYPE::*)>
302: Is_Empty_Class_Imp<t_TYPE>::type {
303};
304
305 // =======================
306 // struct is_empty (C++03)
307 // =======================
308
309/// This `struct` is a meta-function to determine whether the (template
310/// parameter) `t_TYPE` is an empty class type. `is_empty` inherits from
311/// `true_type` if `t_TYPE` is a `class` or `struct` with no non-static data
312/// members other than bit-fields of length 0, no virtual member functions,
313/// no virtual base classes, and no base class `B` for which
314/// `is_empty<B>::value` is `false`; otherwise `is_empty` inherits from `false_type`.
315///
316/// \note Note that this meta-function will fail to compile for a
317/// union that is the same size as an empty class in C++03.
318template <class t_TYPE>
319struct is_empty : Is_Empty_Imp<t_TYPE>::type {
320};
321
322template <class t_TYPE>
323struct is_empty<const t_TYPE> : Is_Empty_Imp<t_TYPE>::type {
324};
325template <class t_TYPE>
326struct is_empty<volatile t_TYPE> : Is_Empty_Imp<t_TYPE>::type {
327};
328template <class t_TYPE>
329struct is_empty<const volatile t_TYPE> : Is_Empty_Imp<t_TYPE>::type {
330};
331 // Partial specializations reduce the total number of template
332 // instantiations when cv-qualified types are involved.
333
334#endif // defined(BSLS_ISEMPTY_USE_NATIVE_TRAIT)
335
336} // close namespace bsl
337
338#endif
339
340// ----------------------------------------------------------------------------
341// Copyright 2019 Bloomberg Finance L.P.
342//
343// Licensed under the Apache License, Version 2.0 (the "License");
344// you may not use this file except in compliance with the License.
345// You may obtain a copy of the License at
346//
347// http://www.apache.org/licenses/LICENSE-2.0
348//
349// Unless required by applicable law or agreed to in writing, software
350// distributed under the License is distributed on an "AS IS" BASIS,
351// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
352// See the License for the specific language governing permissions and
353// limitations under the License.
354// ----------------------------- END-OF-FILE ----------------------------------
355
356/** @} */
357/** @} */
358/** @} */
static const t_TYPE value
Definition bslmf_integralconstant.h:267
#define BSLMF_VOIDTYPE(ARG)
Definition bslmf_voidtype.h:343
#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
integral_constant< bool, sizeof(Derived)==sizeof(int)> type
Definition bslmf_isempty.h:276
Definition bslmf_isempty.h:251
Definition bslmf_isempty.h:292
Definition bslmf_isempty.h:235
Definition bslmf_integralconstant.h:261
Definition bslmf_isempty.h:319