BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmf_nestedtraitdeclaration.h
Go to the documentation of this file.
1/// @file bslmf_nestedtraitdeclaration.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmf_nestedtraitdeclaration.h -*-C++-*-
8#ifndef INCLUDED_BSLMF_NESTEDTRAITDECLARATION
9#define INCLUDED_BSLMF_NESTEDTRAITDECLARATION
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmf_nestedtraitdeclaration bslmf_nestedtraitdeclaration
15/// @brief Provide a nested declaration to associate a class with a trait.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmf
19/// @{
20/// @addtogroup bslmf_nestedtraitdeclaration
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmf_nestedtraitdeclaration-purpose"> Purpose</a>
25/// * <a href="#bslmf_nestedtraitdeclaration-macros"> Macros </a>
26/// * <a href="#bslmf_nestedtraitdeclaration-description"> Description </a>
27/// * <a href="#bslmf_nestedtraitdeclaration-relationship-with-c-11-style-type-traits"> Relationship with "C++11-style" Type Traits </a>
28/// * <a href="#bslmf_nestedtraitdeclaration-usage"> Usage </a>
29/// * <a href="#bslmf_nestedtraitdeclaration-example-1-testing-a-type-for-a-custom-trait"> Example 1: Testing a Type for a Custom Trait </a>
30///
31/// # Purpose {#bslmf_nestedtraitdeclaration-purpose}
32/// Provide a nested declaration to associate a class with a trait.
33///
34/// # Macros {#bslmf_nestedtraitdeclaration-macros}
35///
36/// - BSLMF_NESTED_TRAIT_DECLARATION: macro that associates a trait with a class
37/// - BSLMF_NESTED_TRAIT_DECLARATION_IF: conditional macro to associates a trait
38///
39/// @see bslmf_detectnestedtrait
40///
41/// # Description {#bslmf_nestedtraitdeclaration-description}
42/// This component defines a pair of macros,
43/// `BSLMF_NESTED_TRAIT_DECLARATION` and `BSLMF_NESTED_TRAIT_DECLARATION_IF`,
44/// that can be used in association with the facilities provided by
45/// @ref bslmf_detectnestedtrait to declare that a given class has a given trait.
46///
47/// Traits provide a mechanism for convenient compile-time discovery of
48/// information about a class, which is useful in particular for providing
49/// efficient specializations of generalized containers and algorithms without
50/// having to rely on knowledge of specific target classes.
51///
52/// The primary public interface of this component consists of two macros that
53/// provide a facility for declaring that a given class has a given trait.
54/// These macros embed the association between the type and the trait inside the
55/// class definition itself, hence the term "nested trait declaration".
56///
57/// Note that the term "nested" is not meant to imply that this facility
58/// declares a nested type within the class namespace, only that the trait
59/// declaration appears as one of the public declarations that make up the class
60/// definition. For example, we could declare that a class, `xyza::Foo`, has
61/// the trait `abcd::BarTrait` in the following way:
62/// @code
63/// namespace xyza {
64///
65/// class Foo {
66/// // ... various implementation details ...
67///
68/// public:
69/// // TRAITS
70/// BSLMF_NESTED_TRAIT_DECLARATION(Foo, abcd::BarTrait);
71///
72/// // ... the rest of the public interface ...
73/// };
74///
75/// } // close namespace xyza
76/// @endcode
77/// Two flavors of macro are provided: one for declaring unconditionally that a
78/// class has a trait, and another for declaring that the class has a trait if
79/// and only if a given compile-time expression evaluates to `true`.
80///
81/// ## Relationship with "C++11-style" Type Traits {#bslmf_nestedtraitdeclaration-relationship-with-c-11-style-type-traits}
82///
83///
84/// Traits declared using this component are not automatically compatible
85/// mechanisms designed to detect "C++11-style" traits. For a full discussion
86/// of the relationship between nested traits and "C++11-style" traits, as well
87/// as best practices for defining, associating, and detecting traits, see the
88/// component documentation for @ref bslmf_detectnestedtrait .
89///
90/// ## Usage {#bslmf_nestedtraitdeclaration-usage}
91///
92///
93/// This section illustrates the intended use of this component.
94///
95/// ### Example 1: Testing a Type for a Custom Trait {#bslmf_nestedtraitdeclaration-example-1-testing-a-type-for-a-custom-trait}
96///
97///
98/// When writing generic infrastructure code, we often need to choose among
99/// multiple code paths based on the capabilities of the types on which we are
100/// operating. If those capabilities are reflected in a type's public
101/// interface, we may be able to use techniques such as SFINAE to choose the
102/// appropriate code path. However, SFINAE cannot detect all of a type's
103/// capabilities. In particular, SFINAE cannot detect constructors, memory
104/// allocation, thread-safety characteristics, and so on. Functions that depend
105/// on these capabilities must use another technique to determine the correct
106/// code path to use for a given type. We can solve this sort of problem by
107/// associating types with custom traits that indicate what capabilities are
108/// provided by a given type.
109///
110/// First, assume that a compatible trait, `abcd::RequiresLockTrait`, has been
111/// defined that indicates that a type's methods must not be called unless a
112/// known lock is first acquired:
113/// @code
114/// namespace abcd { template <class t_TYPE> struct RequiresLockTrait; }
115/// @endcode
116/// The implementation of `abcd::RequiresLockTrait` is not shown.
117///
118/// Then, in package `xyza`, we declare a type, `DoesNotRequireLockType`, that
119/// can be used without acquiring the lock:
120/// @code
121/// namespace xyza {
122///
123/// class DoesNotRequireLockType {
124/// // ...
125///
126/// public:
127/// // CREATORS
128/// DoesNotRequireLockType();
129/// // ...
130/// };
131/// @endcode
132/// Next, we declare a type, `RequiresLockType`, that does require the lock. We
133/// use the `BSLMF_NESTED_TRAIT_DECLARATION` macro to associate the type with
134/// the `abcd::RequiresLockTrait` trait:
135/// @code
136/// class RequiresLockType {
137/// // ...
138///
139/// public:
140/// // TRAITS
141/// BSLMF_NESTED_TRAIT_DECLARATION(RequiresLockType,
142/// abcd::RequiresLockTrait);
143///
144/// // CREATORS
145/// RequiresLockType();
146/// // ...
147///
148/// };
149/// @endcode
150/// Notice that the macro declaration is performed within the scope of the class
151/// declaration, and must be done with public scope.
152///
153/// Now, we declare a templatized container type, `Container`, that is
154/// parameterized on some `ELEMENT` type. If `ELEMENT` requires a lock, then a
155/// `Container` of `ELEMENT`s will require a lock as well. This can be
156/// expressed using the `BSLMF_NESTED_TRAIT_DECLARATION_IF` macro, by providing
157/// `abcd::RequiresLockTrait<ELEMENT>::value` as the condition for associating
158/// the trait with `Container`.
159/// @code
160/// template <class ELEMENT>
161/// struct Container {
162/// // ...
163///
164/// public:
165/// // TRAITS
166/// BSLMF_NESTED_TRAIT_DECLARATION_IF(Container, abcd::RequiresLockTrait,
167/// abcd::RequiresLockTrait<ELEMENT>::value);
168///
169/// // ...
170/// };
171///
172/// } // close package namespace
173/// @endcode
174/// Finally, code interacting with `xyza::DoesNotRequireLockType`,
175/// `xyza::RequiresLockType` or `xyza::Container` objects will be able to choose
176/// the appropriate code path by checking for the `abcd::RequiresLockTrait`
177/// trait. See @ref bslmf_detectnestedtrait for an example of how generic code
178/// would use such a trait.
179/// @}
180/** @} */
181/** @} */
182
183/** @addtogroup bsl
184 * @{
185 */
186/** @addtogroup bslmf
187 * @{
188 */
189/** @addtogroup bslmf_nestedtraitdeclaration
190 * @{
191 */
192
193#include <bslscm_version.h>
194
195
196
197namespace bslmf {
198
199 // ============================
200 // class NestedTraitDeclaration
201 // ============================
202
203/// Class `t_TYPE` will be convertible to
204/// `NestedTraitDeclaration<t_TYPE,t_TRAIT,true>` if `t_TRAIT` is associated
205/// with `t_TYPE` using the `BSLMF_NESTED_TRAIT_DECLARATION` macro. Nested
206/// trait detection depends on `t_COND` being true. If `t_COND` is false,
207/// the nested trait detection will not see the conversion it is looking for
208/// and will not associate `t_TRAIT` with `t_TYPE`. This feature is used by
209/// `BSLMF_NESTED_TRAIT_DECLARATION_IF` to turn a trait on or off depending
210/// on a compile-time condition (usually another trait).
211///
212/// See @ref bslmf_nestedtraitdeclaration
213template <class t_TYPE, template <class t_T> class t_TRAIT, bool t_COND = true>
226
227 // ====================================
228 // macro BSLMF_NESTED_TRAIT_DECLARATION
229 // ====================================
230
231#define BSLMF_NESTED_TRAIT_DECLARATION(t_TYPE, t_TRAIT) \
232 operator BloombergLP::bslmf::NestedTraitDeclaration<t_TYPE, t_TRAIT>() \
233 const \
234 { \
235 return BloombergLP::bslmf::NestedTraitDeclaration<t_TYPE, t_TRAIT>(); \
236 }
237
238#ifdef __CDT_PARSER__
239// Work around an Eclise CDT bug where it fails to parse the conditional trait
240// declaration. See internal DRQS 47839133.
241#define BSLMF_NESTED_TRAIT_DECLARATION_IF(t_TYPE, t_TRAIT, t_COND)
242#else
243#define BSLMF_NESTED_TRAIT_DECLARATION_IF(t_TYPE, t_TRAIT, t_COND) \
244 operator BloombergLP::bslmf:: \
245 NestedTraitDeclaration<t_TYPE, t_TRAIT, t_COND>() const \
246 { \
247 return BloombergLP::bslmf:: \
248 NestedTraitDeclaration<t_TYPE, t_TRAIT, t_COND>(); \
249 }
250#endif
251
252} // close package namespace
253
254
255
256#endif // ! defined(INCLUDED_BSLMF_NESTEDTRAITDECLARATION)
257
258// ----------------------------------------------------------------------------
259// Copyright 2013 Bloomberg Finance L.P.
260//
261// Licensed under the Apache License, Version 2.0 (the "License");
262// you may not use this file except in compliance with the License.
263// You may obtain a copy of the License at
264//
265// http://www.apache.org/licenses/LICENSE-2.0
266//
267// Unless required by applicable law or agreed to in writing, software
268// distributed under the License is distributed on an "AS IS" BASIS,
269// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
270// See the License for the specific language governing permissions and
271// limitations under the License.
272// ----------------------------- END-OF-FILE ----------------------------------
273
274/** @} */
275/** @} */
276/** @} */
Definition bslmf_nestedtraitdeclaration.h:214
NestedTraitDeclaration & operator=(const NestedTraitDeclaration &)
NestedTraitDeclaration Type
Definition bslmf_nestedtraitdeclaration.h:218
NestedTraitDeclaration(const NestedTraitDeclaration &)
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlbb_blob.h:576