Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bslmf_forwardingreftype
[Package bslmf]

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:
bslmf::ForwardingRefType meta-function to determine forwarding type
bslmf::ForwardingRefTypeUtil Namespace for forwarding functions
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()
      // Usage example.
  {
      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));
  }