BDE 4.14.0 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
184/// `false`; otherwise `is_empty` defaults to `false_type`. Note that this
185/// meta-function will fail to compile for a union that is the same size as
186/// an empty class in C++03.
187template <class t_TYPE>
188struct is_empty;
189
190} // close namespace bsl
191
192// ============================================================================
193// CLASS TEMPLATE DEFINITIONS
194// ============================================================================
195namespace bsl {
196#if defined(BSLMF_ISEMPTY_USE_NATIVE_TRAIT)
197
198 // =======================
199 // struct is_empty (C++11)
200 // =======================
201
202/// This specification defers to the native trait on supported C++11
203/// compilers.
204template <class t_TYPE>
205struct is_empty
206: bsl::integral_constant<bool, ::std::is_empty<t_TYPE>::value> {
207};
208
209#ifdef BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES
210/// This template variable represents the result value of the
211/// `bsl::is_empty` meta-function.
212template <class t_TYPE>
213BSLS_KEYWORD_INLINE_VARIABLE constexpr bool is_empty_v =
215#endif
216
217#else
218
219 // ====================
220 // struct Is_Empty_Size
221 // ====================
222
223/// Private class: do not use outside of @ref bslmf_isempty component. This
224/// component-private class is an example of an empty type, that can be used
225/// to calculate the likely size of an empty type on the current platform.
226/// As the inheritance-based technique used below disallows unions with a
227/// hard error, rather than a SFINAE-friendly failure, it is important to
228/// avoid instantiating the `Imp` test unless there is a real chance that
229/// the type might be empty. While we cannot protect against testing small
230/// unions, we can rule out the more common cases where at least one union
231/// member has more than the smallest permissible size on the current ABI.
233};
234
235 // =========================
236 // struct Is_Empty_Class_Imp
237 // =========================
238
239/// Private class: do not use outside of @ref bslmf_isempty component. This
240/// meta-function derives from `false_type` unless (the template parameter)
241/// `t_TYPE` is exactly the same size as a known empty type, in which case
242/// the following partial specialization is chosen. This test filters out
243/// the majority of problems with `union` types that are classes, and would
244/// produce a hard, non-SFINAEable error trying to a create a derived class
245/// to compare size in the next test.
246template <class t_TYPE,
247 bool IS_CLASS = sizeof(t_TYPE) == sizeof(Is_Empty_Size)>
250
251/// Private class: do not use outside of @ref bslmf_isempty component.
252/// Implementation of `bsl::is_empty` for class types that are small enough
253/// that they might be an empty class.
254template <class t_TYPE>
255struct Is_Empty_Class_Imp<t_TYPE, true> {
256
257 private:
258 /// This `struct` derives from the template parameter `t_TYPE` from the
259 /// enclosing class template, and will have the same size as an `int` if
260 /// `t_TYPE` is an empty class, and a larger size otherwise.
261 struct Derived : t_TYPE {
262
263 Derived(); // Declared but not defined
264 Derived(const Derived&); // Declared but not defined
265 ~Derived(); // Declared but not defined
266
267 int d_data; // 'Derived' is not empty
268 };
269
270 public:
271 /// `true_type` if (the template parameter) `t_TYPE` is an empty class,
272 /// and `false_type` otherwise.
273 typedef integral_constant<bool, sizeof(Derived) == sizeof(int)> type;
274};
275
276 // ===================
277 // struct Is_Empty_Imp
278 // ===================
279
280/// Private class: do not use outside of @ref bslmf_isempty component. This
281/// meta-function provides an initial dispatch that always derives from
282/// `false_type` unless the template parameter `t_TYPE` is a class type, as
283/// only class types can be empty. The following partial specialization
284/// forwards all class types to a final test. This two-phase dispatch is
285/// necessary as some types, such as `void` and function types, cannot be
286/// passed to a `sizeof` operator that is used to implement the next stage
287/// of matching.
288template <class t_TYPE, class = void>
290};
291
292/// Private class: do not use outside of @ref bslmf_isempty component.
293/// Implementation of `bsl::is_empty`. This partial specialization derives
294/// from the nested `type` member of the `Is_Empty_Class_Imp` meta-function,
295/// which must be `true_type` if (the template parameter) `t_TYPE` is an
296/// empty class, and `false_type` otherwise.
297template <class t_TYPE>
298struct Is_Empty_Imp<t_TYPE, BSLMF_VOIDTYPE(int t_TYPE::*)>
299: Is_Empty_Class_Imp<t_TYPE>::type {
300};
301
302 // =======================
303 // struct is_empty (C++03)
304 // =======================
305
306/// This `struct` is a meta-function to determine whether the (template
307/// parameter) `t_TYPE` is an empty class type. `is_empty` inherits from
308/// `true_type` if `t_TYPE` is a `class` or `struct` with no non-static data
309/// members other than bit-fields of length 0, no virtual member functions,
310/// no virtual base classes, and no base class `B` for which
311/// `is_empty<B>::value` is `false`; otherwise `is_empty` inherits from
312/// `false_type`. Note that this meta-function will fail to compile for a
313/// union that is the same size as an empty class in C++03.
314template <class t_TYPE>
315struct is_empty : Is_Empty_Imp<t_TYPE>::type {
316};
317
318template <class t_TYPE>
319struct is_empty<const t_TYPE> : Is_Empty_Imp<t_TYPE>::type {
320};
321template <class t_TYPE>
322struct is_empty<volatile t_TYPE> : Is_Empty_Imp<t_TYPE>::type {
323};
324template <class t_TYPE>
325struct is_empty<const volatile t_TYPE> : Is_Empty_Imp<t_TYPE>::type {
326};
327 // Partial specializations reduce the total number of template
328 // instantiations when cv-qualified types are involved.
329
330#endif // defined(BSLS_ISEMPTY_USE_NATIVE_TRAIT)
331
332} // close namespace bsl
333
334#endif
335
336// ----------------------------------------------------------------------------
337// Copyright 2019 Bloomberg Finance L.P.
338//
339// Licensed under the Apache License, Version 2.0 (the "License");
340// you may not use this file except in compliance with the License.
341// You may obtain a copy of the License at
342//
343// http://www.apache.org/licenses/LICENSE-2.0
344//
345// Unless required by applicable law or agreed to in writing, software
346// distributed under the License is distributed on an "AS IS" BASIS,
347// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
348// See the License for the specific language governing permissions and
349// limitations under the License.
350// ----------------------------- END-OF-FILE ----------------------------------
351
352/** @} */
353/** @} */
354/** @} */
static const t_TYPE value
Definition bslmf_integralconstant.h:258
#define BSLMF_VOIDTYPE(ARG)
Definition bslmf_voidtype.h:335
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_INLINE_VARIABLE
Definition bsls_keyword.h:623
Definition bdlb_printmethods.h:283
integral_constant< bool, sizeof(Derived)==sizeof(int)> type
Definition bslmf_isempty.h:273
Definition bslmf_isempty.h:248
Definition bslmf_isempty.h:289
Definition bslmf_isempty.h:232
Definition bslmf_integralconstant.h:244
Definition bslmf_isempty.h:315