Provide a meta-function for determining a forwarding type.
More...
Namespaces |
namespace | bslmf |
Detailed Description
- Outline
-
-
- Purpose:
- Provide a meta-function for determining a forwarding type.
-
- Classes:
-
- See also:
- Component bslmf_removecvq
-
- Description:
- This component provides a meta function,
bslmf::ForwardingReftype
, that determines the forwarding type for a given template type t_TYPE
. A FowardingRefType
is type used as a parameter type in template functions that seek to "forward" their arguments to an underlying function in a way that is type safe and efficient. This component also provides a utility class template, bslmf::ForwardingRefTypeUtil
, that primarily supplies a function bslmf::ForwadingRefTypeUtil::forwardToTarget
that forwards an argument to another function.
- An argument
v
of type T
can be passed as type ForwardingRefType<T>Type
down an arbitrarily-long chain of function calls without ever calling std::forward
. However, in order to avoid an extra copy as well as to select the correct overload and instantiation of the eventual target function, it should be converted back to a type that more closely resembles the original T
by calling ForwardingRefTypeUtil<T>forwardToTarget(v)
.
- One optimization performed by this component is the early decay of arrays to pointers, preventing a proliferation of different template instantiations for every array size being used. Although the outermost function may still be instantiated on the full array type, intermediate functions are all instantiated on the same pointer type, regardless of array size. This decay also applies to reference-to-array types. The user can recover the original array type when forwarding to the final consumer by using
bslmf::ForwardingRefTypeUtil<T>forwardToTarget()
(see below).
-
- Comparison To bslmf_forwardingtype:
- The components
bslmf_forwardingtype
and bslmf_forwardingreftype
serve the same purpose but have small behavioral differences. In general, we recommend bslmf_forwardingreftype
(the new component) in most contexts.
- Most notably,
bslmf::ForwardingType
(the older class) forwards fundamental and pointer types by value, where as bslmf::ForwardingRefType
will forward fundamental and pointer types by const-reference. For example, bslmf::ForwardingType<int>Type
is int
where as bslmf::ForwardingRefType<int>Type
is const int&
. This applies to fundamental types, pointer types (including member-pointer types), and enum types (which we'll collectively call "basic types"). Forwarding these basic types by value was a performance optimization (and in some rare circumstances was hack needed by older compilers), which predated the standardization of many of the places where bslmf::ForwardingType
was used (function and bind components in particular). The optimzation (potentially) being that passing an int
by value is more likely to be done through a register, where as passing by reference is more likely to require de-referencing memory. Forwarding the types by const-reference, as the newer bslmf::ForwardingRefType
does', is generally simpler and more in line with the modern C++ standard. Using bslmf::ForwardingRefType
avoids some awkward edge cases at the expense of a possible optimization in parameter passing.
-
- Usage:
- In this section we show intended use of this component.
-
- Example 1: Direct Look at Metafunction Results:
- In this example, we invoke
ForwardingRefType
on a variety of types and look at the resulting Type
member: struct MyType {};
typedef MyType& MyTypeRef;
void main()
{
typedef int T1;
typedef int& T2;
typedef const volatile double& T3;
typedef const double & T4;
typedef const float * & T5;
typedef const float * const & T6;
typedef MyType T7;
typedef const MyType& T8;
typedef MyType& T9;
typedef MyType *T10;
typedef int T11[];
typedef int T12[3];
typedef const int& EXP1;
typedef int& EXP2;
typedef const volatile double& EXP3;
typedef const double & EXP4;
typedef const float * & EXP5;
typedef const float * const & EXP6;
typedef const MyType& EXP7;
typedef const MyType& EXP8;
typedef MyType& EXP9;
typedef MyType * const & EXP10;
typedef int * const & EXP11;
typedef int * const & EXP12;
using bslmf::ForwardingRefType;
ASSERT((bsl::is_same<ForwardingRefType<T1>::Type, EXP1>::value));
ASSERT((bsl::is_same<ForwardingRefType<T2>::Type, EXP2>::value));
ASSERT((bsl::is_same<ForwardingRefType<T3>::Type, EXP3>::value));
ASSERT((bsl::is_same<ForwardingRefType<T4>::Type, EXP4>::value));
ASSERT((bsl::is_same<ForwardingRefType<T5>::Type, EXP5>::value));
ASSERT((bsl::is_same<ForwardingRefType<T6>::Type, EXP6>::value));
ASSERT((bsl::is_same<ForwardingRefType<T7>::Type, EXP7>::value));
ASSERT((bsl::is_same<ForwardingRefType<T8>::Type, EXP8>::value));
ASSERT((bsl::is_same<ForwardingRefType<T9>::Type, EXP9>::value));
ASSERT((bsl::is_same<ForwardingRefType<T10>::Type, EXP10>::value));
ASSERT((bsl::is_same<ForwardingRefType<T11>::Type, EXP11>::value));
ASSERT((bsl::is_same<ForwardingRefType<T12>::Type, EXP12>::value));
}