BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslmf_util.h
Go to the documentation of this file.
1/// @file bslmf_util.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmf_util.h -*-C++-*-
8#ifndef INCLUDED_BSLMF_UTIL
9#define INCLUDED_BSLMF_UTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmf_util bslmf_util
15/// @brief Provide low-level functions on `bslmf` types.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmf
19/// @{
20/// @addtogroup bslmf_util
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmf_util-purpose"> Purpose</a>
25/// * <a href="#bslmf_util-classes"> Classes </a>
26/// * <a href="#bslmf_util-description"> Description </a>
27/// * <a href="#bslmf_util-bslmf-util-forward"> bslmf::Util::forward </a>
28/// * <a href="#bslmf_util-bslmf-util-forwardasreference"> bslmf::Util::forwardAsReference </a>
29/// * <a href="#bslmf_util-bslmf-util-moveifsupported"> bslmf::Util::moveIfSupported </a>
30/// * <a href="#bslmf_util-usage"> Usage </a>
31/// * <a href="#bslmf_util-example-1-using-bslmf-util-forward"> Example 1: Using bslmf::Util::forward </a>
32/// * <a href="#bslmf_util-example-2-using-bslmf-util-forwardasreference"> Example 2: Using bslmf::Util::forwardAsReference </a>
33/// * <a href="#bslmf_util-example-3-using-bslmf-util-moveifsupported"> Example 3: Using bslmf::Util::moveIfSupported </a>
34///
35/// # Purpose {#bslmf_util-purpose}
36/// Provide low-level functions on `bslmf` types.
37///
38/// # Classes {#bslmf_util-classes}
39///
40/// - bslmf::Util: utility class providing low-level functionality
41///
42/// # Description {#bslmf_util-description}
43/// This component defines a utility `struct`, `bslmf::Util`, that
44/// serves as a namespace for a suite of functions that supply low-level
45/// functionality for implementing portable generic facilities such as might be
46/// found in the C++ standard library.
47///
48/// ## bslmf::Util::forward {#bslmf_util-bslmf-util-forward}
49///
50///
51/// The function `forward` emulates the C++ standard utility function
52/// `std::forward` with the addition that on compilers that don't support
53/// r-value references (i.e., C++03) a `bslmf::MovableRef<t_T>` is forwarded as
54/// a `bslmf::MovableRef<t_T>`. This operation is typically used via
55/// `BSLS_COMPILERFEATURES_FORWARD` (along with
56/// `BSLS_COMPILERFEATURES_FORWARD_REF`) when forwarding arguments in a generic
57/// context. See {Usage}.
58///
59/// ## bslmf::Util::forwardAsReference {#bslmf_util-bslmf-util-forwardasreference}
60///
61///
62/// The function `forwardAsReference`, like `forward`, emulates the C++ standard
63/// utility function `std::forward` with the difference that on compilers that
64/// don't support r-value references (C++03) a `bslmf::MovableRef<t_T>` is
65/// forwarded as `const t_T&` (instead of `bslmf::MovableRef<t_T>`). This
66/// operation is intended to be used when forwarding a `MovableRef<t_T>` where
67/// that `MovableRef` is being supplied to a function that does not support
68/// `move` emulation, but will support true C++11 r-value references (e.g.,
69/// `bdlf::BindUtil::bind`).
70///
71/// ## bslmf::Util::moveIfSupported {#bslmf_util-bslmf-util-moveifsupported}
72///
73///
74/// The function `moveIfSupported` emulates the C++ standard utility function
75/// `std::move` with the addition that on compilers that don't support r-value
76/// references (i.e., C++03) an l-value reference is returned instead. This
77/// operation is intended to be used when moving an object to a function that
78/// does not support `move` emulation, but will support true C++11 r-value
79/// references (e.g., `bdlf::BindUtil::bind`).
80///
81/// ## Usage {#bslmf_util-usage}
82///
83///
84/// This section illustrates intended use of this component.
85///
86/// ## Example 1: Using bslmf::Util::forward {#bslmf_util-example-1-using-bslmf-util-forward}
87///
88///
89/// Clients should generally not use `bslmf::Util::forward` directly, instead it
90/// should be used via `BSLS_COMPILERFEATURES_FORWARD` in conjunction with
91/// `BSLS_COMPILERFEATURES_FORWARD_REF`. Here we show a simple function using
92/// `BSLS_COMPILERFEATURES_FORWARD`:
93/// @code
94/// template <class RESULT_TYPE>
95/// struct FactoryUtil {
96///
97/// template <class ARG_TYPE>
98/// RESULT_TYPE create(BSLS_COMPILERFEATURES_FORWARD_REF(ARG_TYPE) arg) {
99/// return RESULT_TYPE(BSLS_COMPILERFEATURES_FORWARD(ARG_TYPE, arg));
100/// }
101/// };
102/// @endcode
103/// Notice that `bslmf::Util::forward` is only used in conjunction with
104/// `BSLS_COMPILERFEATURES_FORWARD_REF` because, in the example above, if the
105/// `create` function's parameter type was `ARG_TYPE&& ` then it is a
106/// C++11-only(!) forwarding reference, and we would simply use the standard
107/// `std::forward`. Alternatively, if the parameter type was
108/// `MovableRef<ARG_TYPE>` then `arg` is *not* a forwarding-reference to be
109/// forwarded (certainly not in C++03).
110///
111/// ## Example 2: Using bslmf::Util::forwardAsReference {#bslmf_util-example-2-using-bslmf-util-forwardasreference}
112///
113///
114/// Suppose we have a class `S1` that has a regular copy constructor, and only
115/// if the compiler supports rvalue references has to move constructor. We want
116/// to construct it with the move constructor if moves are supported and as a
117/// copy otherwise. Then we use `bslmf::Util::forwardAsReference`:
118/// @code
119/// struct S {
120/// S();
121/// S(const S&);
122/// #ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
123/// S(S&&);
124/// #endif
125/// };
126///
127/// S::S() {}
128///
129/// S::S(const S&)
130/// {
131/// printf("S copy c'tor\n");
132/// }
133///
134/// #ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
135/// S::S(S&&)
136/// {
137/// printf("S move c'tor\n");
138/// }
139/// #endif
140///
141/// void doThis2(S s)
142/// {
143/// // ...
144/// }
145///
146/// void doThat2(bslmf::MovableRef<S> value)
147/// {
148/// doThis2(bslmf::Util::forwardAsReference<S>(value));
149/// }
150/// @endcode
151///
152/// ## Example 3: Using bslmf::Util::moveIfSupported {#bslmf_util-example-3-using-bslmf-util-moveifsupported}
153///
154///
155/// Suppose we had a function that takes a non-const lvalue-ref, and only when
156/// the compiler supports rvalue references also has an overload that takes
157/// rvalue references:
158/// @code
159/// void doSomething(S&)
160/// {
161/// printf("doSomething lvalue-ref\n");
162/// }
163///
164/// #ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
165/// void doSomething(S&&)
166/// {
167/// printf("doSomething rvalue-ref\n");
168/// }
169/// #endif
170///
171/// void doSomethingElse(S value)
172/// {
173/// doSomething(bslmf::Util::moveIfSupported(value));
174/// }
175/// @endcode
176/// @}
177/** @} */
178/** @} */
179
180/** @addtogroup bsl
181 * @{
182 */
183/** @addtogroup bslmf
184 * @{
185 */
186/** @addtogroup bslmf_util
187 * @{
188 */
189
190#include <bslscm_version.h>
191
194#include <bslmf_movableref.h>
196
197#include <bsla_nodiscard.h>
198
200#include <bsls_cpp11.h>
201#include <bsls_keyword.h>
202
203
204
205namespace bslmf {
206
207 // ===========
208 // struct Util
209 // ===========
210
211/// This struct provides several functions that are specified in the
212/// <utility> header of the C++ Standard, in order to support the `bsl`
213/// library implementation without cycles into the native standard library,
214/// and on platforms with only C++03 compilers available, where library
215/// features may be emulated.
216///
217/// See @ref bslmf_util
218struct Util {
219
220 // CLASS METHODS
221#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
222 template <class t_TYPE>
223 BSLS_KEYWORD_CONSTEXPR static t_TYPE&& forward(
225 template <class t_TYPE>
226 BSLS_KEYWORD_CONSTEXPR static t_TYPE&& forward(
228#else
229 template <class t_TYPE>
230 BSLS_KEYWORD_CONSTEXPR static const t_TYPE& forward(
231 const t_TYPE& t) BSLS_KEYWORD_NOEXCEPT;
232 template <class t_TYPE>
235#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
236 // Correctly forward the specified 't' argument based on the current
237 // compilation environment.
238
239#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
240 template <class t_MODEL, class t_TYPE>
245 t_TYPE&& t,
246 typename bsl::enable_if<
249 typename bsl::remove_reference<t_MODEL>::type>::value>::type * = 0)
251 template <class t_MODEL, class t_TYPE>
254 t_TYPE&
256 t_TYPE&& t,
257 typename bsl::enable_if<
258 bsl::is_lvalue_reference<t_MODEL>::value &&
259 !bsl::is_const<
260 typename bsl::remove_reference<t_MODEL>::type>::value>::type * = 0)
262 template <class t_MODEL, class t_TYPE>
265 const typename bsl::remove_reference<t_TYPE>::type&&
267 t_TYPE&& t,
268 typename bsl::enable_if<
269 !bsl::is_lvalue_reference<t_MODEL>::value &&
270 bsl::is_const<
271 typename bsl::remove_reference<t_MODEL>::type>::value>::type * = 0)
273 template <class t_MODEL, class t_TYPE>
276 typename bsl::remove_reference<t_TYPE>::type&&
278 t_TYPE&& t,
279 typename bsl::enable_if<
280 !bsl::is_lvalue_reference<t_MODEL>::value &&
281 !bsl::is_const<
282 typename bsl::remove_reference<t_MODEL>::type>::value>::type * = 0)
284#else
285 template <class t_MODEL, class t_TYPE>
288 const t_TYPE&
291 typename bsl::enable_if<
294 t_MODEL>::type>::value>::type * = 0)
296 template <class t_MODEL, class t_TYPE>
299 const t_TYPE&
301 t_TYPE& t,
302 typename bsl::enable_if<
303 bslmf::MovableRefUtil::IsLvalueReference<t_MODEL>::value &&
304 bsl::is_const<typename bslmf::MovableRefUtil::RemoveReference<
305 t_MODEL>::type>::value>::type * = 0)
307 template <class t_MODEL, class t_TYPE>
310 t_TYPE&
312 bslmf::MovableRef<t_TYPE> t,
313 typename bsl::enable_if<
314 bslmf::MovableRefUtil::IsLvalueReference<t_MODEL>::value &&
315 !bsl::is_const<typename bslmf::MovableRefUtil::RemoveReference<
316 t_MODEL>::type>::value>::type * = 0)
318 template <class t_MODEL, class t_TYPE>
321 t_TYPE&
323 t_TYPE& t,
324 typename bsl::enable_if<
325 bslmf::MovableRefUtil::IsLvalueReference<t_MODEL>::value &&
326 !bsl::is_const<typename bslmf::MovableRefUtil::RemoveReference<
327 t_MODEL>::type>::value>::type * = 0)
329 template <class t_MODEL, class t_TYPE>
332 MovableRef<const t_TYPE>
334 bslmf::MovableRef<t_TYPE> t,
335 typename bsl::enable_if<
336 !bslmf::MovableRefUtil::IsLvalueReference<t_MODEL>::value &&
337 bsl::is_const<typename bslmf::MovableRefUtil::RemoveReference<
338 t_MODEL>::type>::value>::type * = 0)
340 template <class t_MODEL, class t_TYPE>
343 MovableRef<const t_TYPE>
345 t_TYPE& t,
346 typename bsl::enable_if<
347 !bslmf::MovableRefUtil::IsLvalueReference<t_MODEL>::value &&
348 bsl::is_const<typename bslmf::MovableRefUtil::RemoveReference<
349 t_MODEL>::type>::value>::type * = 0)
351 template <class t_MODEL, class t_TYPE>
354 MovableRef<t_TYPE>
356 bslmf::MovableRef<t_TYPE> t,
357 typename bsl::enable_if<
358 !bslmf::MovableRefUtil::IsLvalueReference<t_MODEL>::value &&
359 !bsl::is_const<typename bslmf::MovableRefUtil::RemoveReference<
360 t_MODEL>::type>::value>::type * = 0)
362 template <class t_MODEL, class t_TYPE>
365 MovableRef<t_TYPE>
367 t_TYPE& t,
368 typename bsl::enable_if<
369 !bslmf::MovableRefUtil::IsLvalueReference<t_MODEL>::value &&
370 !bsl::is_const<typename bslmf::MovableRefUtil::RemoveReference<
371 t_MODEL>::type>::value>::type * = 0)
373#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
374 // Return an lvalue reference to the specified 't' if the (template
375 // parameter) 't_MODEL' is an lvalue reference; otherwise, return
376 // either an rvalue reference or a 'bslmf::MovableRef' referring to
377 // 't', depending on the current compilation environment. The const
378 // type qualifier is added to the result referenced type if 't_MODEL'
379 // is a const-qualified type or reference thereof.
380
381#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
382 template <class t_TYPE>
384 typename bsl::add_rvalue_reference<t_TYPE>::type
386#else
387 template <class t_TYPE>
391#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
392 // This function has no implementation. It exists to allow for the
393 // appearance of a temporary object of the specified type that can be
394 // used in unevaluated contexts.
395
396#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
397 template <class t_TYPE>
400 template <class t_TYPE>
403#else
404 template <class t_TYPE>
405 BSLS_KEYWORD_CONSTEXPR static const t_TYPE& forwardAsReference(
406 const t_TYPE& t) BSLS_KEYWORD_NOEXCEPT;
407 template <class t_TYPE>
408 BSLS_KEYWORD_CONSTEXPR static const t_TYPE& forwardAsReference(
410#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
411 // Correctly forward the specified 't' argument as a reference type
412 // based on the current compilation environment. Note that this
413 // function differs from 'forward' in that when using a C++03 compiler,
414 // 'MovableRef<t_T>' is forwarded as 'const t_T&' (rather than
415 // 'MovableRef<t_T>'), which is important when forwarding to a facility
416 // (e.g., 'bdlf::BindUtil::bind') which does not support
417 // 'bslmf::MovableRef'.
418
419#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
420 template <class t_TYPE>
424#else
425 template <class t_TYPE>
428#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
429 // Return an r-value reference to the specified 't' argument. If
430 // r-value references are not supported, return an l-value reference.
431};
432
433// ============================================================================
434// INLINE FUNCTION DEFINITIONS
435// ============================================================================
436
437 // -----------
438 // struct Util
439 // -----------
440// CLASS METHODS
441#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
442template <class t_TYPE>
444t_TYPE&& Util::forward(
446{
447 return static_cast<t_TYPE&&>(t);
448}
449
450template <class t_TYPE>
452t_TYPE&& Util::forward(
454{
455 return static_cast<t_TYPE&&>(t);
456}
457
458#else
459
460template <class t_TYPE>
462const t_TYPE& Util::forward(const t_TYPE& t) BSLS_KEYWORD_NOEXCEPT
463{
464 return t;
465}
466
467template <class t_TYPE>
474#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
475
476#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
477template <class t_MODEL, class t_TYPE>
481 t_TYPE&& t,
482 typename bsl::enable_if<
485 typename bsl::remove_reference<t_MODEL>::type>::value>::type *)
487{
488 return t;
489}
490
491template <class t_MODEL, class t_TYPE>
493t_TYPE&
495 t_TYPE&& t,
496 typename bsl::enable_if<
499 typename bsl::remove_reference<t_MODEL>::type>::value>::type *)
501{
502 return static_cast<t_TYPE&>(t);
503}
504
505template <class t_MODEL, class t_TYPE>
509 t_TYPE&& t,
510 typename bsl::enable_if<
513 typename bsl::remove_reference<t_MODEL>::type>::value>::type *)
515{
516 return static_cast<typename bsl::remove_reference<t_TYPE>::type&&>(t);
517}
518
519template <class t_MODEL, class t_TYPE>
523 t_TYPE&& t,
524 typename bsl::enable_if<
527 typename bsl::remove_reference<t_MODEL>::type>::value>::type *)
529{
530 return static_cast<typename bsl::remove_reference<t_TYPE>::type&&>(t);
531}
532#else
533template <class t_MODEL, class t_TYPE>
535const t_TYPE&
538 typename bsl::enable_if<
541 t_MODEL>::type>::value>::type *)
543{
544 return static_cast<const t_TYPE&>(t);
545}
546
547template <class t_MODEL, class t_TYPE>
549const t_TYPE&
551 t_TYPE& t,
552 typename bsl::enable_if<
555 t_MODEL>::type>::value>::type *)
557{
558 return static_cast<const t_TYPE&>(t);
559}
560
561template <class t_MODEL, class t_TYPE>
563t_TYPE&
566 typename bsl::enable_if<
569 t_MODEL>::type>::value>::type *)
571{
572 return static_cast<t_TYPE&>(t);
573}
574
575template <class t_MODEL, class t_TYPE>
577t_TYPE&
579 t_TYPE& t,
580 typename bsl::enable_if<
583 t_MODEL>::type>::value>::type *)
585{
586 return t;
587}
588
589template <class t_MODEL, class t_TYPE>
594 typename bsl::enable_if<
597 t_MODEL>::type>::value>::type *)
599{
600 return bslmf::MovableRefUtil::move(static_cast<const t_TYPE&>(t));
601}
602
603template <class t_MODEL, class t_TYPE>
607 t_TYPE& t,
608 typename bsl::enable_if<
611 t_MODEL>::type>::value>::type *)
613{
614 return bslmf::MovableRefUtil::move(static_cast<const t_TYPE&>(t));
615}
616
617template <class t_MODEL, class t_TYPE>
631
632template <class t_MODEL, class t_TYPE>
645#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
646
647#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
648template <class t_TYPE>
652{
653 return static_cast<t_TYPE&&>(t);
654}
655
656template <class t_TYPE>
660{
661 return static_cast<t_TYPE&&>(t);
662}
663
664#else
665
666template <class t_TYPE>
669{
670 return t;
671}
672
673template <class t_TYPE>
680#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
681
682#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
683template <class t_T>
686 t_T&& t) BSLS_KEYWORD_NOEXCEPT
687{
688 return static_cast<typename bsl::remove_reference<t_T>::type&&>(t);
689}
690
691#else
692
693template <class t_T>
697{
698 return static_cast<typename bsl::remove_reference<t_T>::type&>(t);
699}
700#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
701
702} // close package namespace
703
704
705#endif
706
707// ----------------------------------------------------------------------------
708// Copyright 2016 Bloomberg Finance L.P.
709//
710// Licensed under the Apache License, Version 2.0 (the "License");
711// you may not use this file except in compliance with the License.
712// You may obtain a copy of the License at
713//
714// http://www.apache.org/licenses/LICENSE-2.0
715//
716// Unless required by applicable law or agreed to in writing, software
717// distributed under the License is distributed on an "AS IS" BASIS,
718// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
719// See the License for the specific language governing permissions and
720// limitations under the License.
721// ----------------------------- END-OF-FILE ----------------------------------
722
723/** @} */
724/** @} */
725/** @} */
Definition bslmf_movableref.h:752
#define BSLA_NODISCARD
Definition bsla_nodiscard.h:320
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_CONSTEXPR
Definition bsls_keyword.h:624
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
Definition bdlat_valuetypefunctions.h:939
Definition bdlbb_blob.h:579
t_TYPE & type
This typedef defines the return type of this meta function.
Definition bslmf_addlvaluereference.h:131
Definition bslmf_enableif.h:530
Definition bslmf_isconst.h:145
Definition bslmf_islvaluereference.h:135
t_TYPE type
This typedef is an alias to the (template parameter) t_TYPE.
Definition bslmf_removereference.h:156
Definition bslmf_movableref.h:805
Definition bslmf_movableref.h:829
Definition bslmf_movableref.h:795
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1067
static t_TYPE & access(t_TYPE &ref) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1039
Definition bslmf_removereference.h:219
Definition bslmf_util.h:218
static BSLS_KEYWORD_CONSTEXPR bsl::add_lvalue_reference< t_TYPE >::type declval() BSLS_KEYWORD_NOEXCEPT
static BSLS_KEYWORD_CONSTEXPR MovableRef< t_TYPE > forward(MovableRef< t_TYPE > t) BSLS_KEYWORD_NOEXCEPT
static BSLS_KEYWORD_CONSTEXPR const t_TYPE & forward(const t_TYPE &t) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_util.h:462
static BSLS_KEYWORD_CONSTEXPR bsl::remove_reference< t_TYPE >::type & moveIfSupported(t_TYPE &t) BSLS_KEYWORD_NOEXCEPT
static BSLA_NODISCARD BSLS_KEYWORD_CONSTEXPR const t_TYPE & forward_like(bslmf::MovableRef< t_TYPE > t, typename bsl::enable_if< bslmf::MovableRefUtil::IsLvalueReference< t_MODEL >::value &&bsl::is_const< typename bslmf::MovableRefUtil::RemoveReference< t_MODEL >::type >::value >::type *=0) BSLS_KEYWORD_NOEXCEPT
static BSLS_KEYWORD_CONSTEXPR const t_TYPE & forwardAsReference(const t_TYPE &t) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_util.h:668