Provide a meta-function to decay and unwrap reference wrappers.
Outline
Purpose
Provide a meta-function to decay and unwrap reference wrappers.
Classes
- bsl::unwrap_ref_decay: standard meta-function to unwrap decayed ref wrapper
- bsl::unwrap_ref_decay_t: alias to the return type of the meta-function
Canonical Header
bsl_functional.h, bsl_type_traits.h
- See also
- bslmf_referencewrapper, bslmf_unwrap_reference
Description
This component defines a meta-function bsl::unwrap_ref_decay that may be used to unwrap a possibly cv-qualified bsl::reference_wrapper (which is an alias of std::reference_wrapper if that exists) specialization or reference thereto of some type U, resulting in U&. In case the specified type template argument is not a specialization of bsl::reference_wrapper the result is the type, but decayed (bsl::decay).
bsl::unwrap_ref_decay meets the requirements of the unwrap_ref_decay template defined in the C++20 standard [meta.trans.other].
Usage
In this section we show intended use of this component.
Example 1: Unwrap Reference Wrapped Argument Types
Suppose that we work in a programming environment where function argument types may be presented as is, or wrapped in a bsl::reference_wrapper and we would like to create a member or local variable while obeying the request for the reference type that the reference-wrapper represents. As parameters may be cv-qualified and may be references we need to first decay them (see bsl::decay). When the argument type decays into a reference-wrapper we want to use a reference to the wrapped type, and simply use the decayed variations of types that are not wrapped. This is a use case for bsl::unwrap_ref_decay.
First, we create types that may be the bases for reference-wrapped, and normal type parameters:
typedef int *NotWrappedType;
Definition bslmf_referencewrapper.h:182
Next, we create types that represent possible function argument types:
typedef WrappedType WrappedTypeArray[5];
typedef WrappedType *WrappedTypePointer;
typedef const WrappedType ConstWrappedType;
typedef volatile WrappedType VolatileWrappedType;
typedef const volatile WrappedType CvWrappedType;
typedef WrappedType& WrappedTypeRef;
typedef const WrappedType& ConstWrappedTypeRef;
typedef volatile WrappedType& VolatileWrappedTypeRef;
typedef const volatile WrappedType& CvWrappedTypeRef;
typedef NotWrappedType NotWrappedTypeArray[5];
typedef NotWrappedType *NotWrappedTypePointer;
typedef const NotWrappedType ConstNotWrappedType;
typedef volatile NotWrappedType VolatileNotWrappedType;
typedef const volatile NotWrappedType CvNotWrappedType;
typedef NotWrappedType& NotWrappedTypeRef;
typedef const NotWrappedType& ConstNotWrappedTypeRef;
typedef volatile NotWrappedType& VolatileNotWrappedTypeRef;
typedef const volatile NotWrappedType& CvNotWrappedTypeRef;
Finally we can verify and demonstrate how all these types turn into a decayed type, and only those that decay into a reference-wrapper type will become themselves references. Notice that an array of reference wrappers decays into a pointer to a wrapper, so it will not turn into a reference.
assert((
true ==
bsl::is_same<bsl::unwrap_ref_decay<WrappedTypeArray>::type,
WrappedType *>::value));
bsl::unwrap_ref_decay<WrappedTypePointer>::type,
WrappedTypePointer>::value));
assert((
true ==
bsl::is_same<bsl::unwrap_ref_decay<WrappedType>::type,
int *&>::value));
bsl::unwrap_ref_decay<ConstWrappedType>::type,
int *&>::value));
bsl::unwrap_ref_decay<VolatileWrappedType>::type,
int *&>::value));
assert((
true ==
bsl::is_same<bsl::unwrap_ref_decay<CvWrappedType>::type,
int *&>::value));
assert((
true ==
bsl::is_same<bsl::unwrap_ref_decay<WrappedTypeRef>::type,
int *&>::value));
bsl::unwrap_ref_decay<ConstWrappedTypeRef>::type,
int *&>::value));
bsl::unwrap_ref_decay<VolatileWrappedTypeRef>::type,
int *&>::value));
assert((
true ==
bsl::is_same<bsl::unwrap_ref_decay<CvWrappedTypeRef>::type,
int *&>::value));
bsl::unwrap_ref_decay<NotWrappedTypeArray>::type,
NotWrappedType *>::value));
bsl::unwrap_ref_decay<NotWrappedTypePointer>::type,
NotWrappedTypePointer>::value));
assert((
true ==
bsl::is_same<bsl::unwrap_ref_decay<NotWrappedType>::type,
NotWrappedType>::value));
bsl::unwrap_ref_decay<ConstNotWrappedType>::type,
NotWrappedType>::value));
bsl::unwrap_ref_decay<VolatileNotWrappedType>::type,
NotWrappedType>::value));
assert((
true ==
bsl::is_same<bsl::unwrap_ref_decay<CvNotWrappedType>::type,
NotWrappedType>::value));
bsl::unwrap_ref_decay<NotWrappedTypeRef>::type,
NotWrappedType>::value));
bsl::unwrap_ref_decay<ConstNotWrappedTypeRef>::type,
NotWrappedType>::value));
bsl::unwrap_ref_decay<VolatileNotWrappedTypeRef>::type,
NotWrappedType>::value));
bsl::unwrap_ref_decay<CvNotWrappedTypeRef>::type,
NotWrappedType>::value));
Definition bslmf_issame.h:146
Note, that (when available) the bsl::unwrap_ref_decay_t avoids the ::type suffix and typename prefix when we want to use the result of the bsl::unwrap_ref_decay meta-function in templates.