Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bslmf_isreferencewrapper
[Package bslmf]

Provide a trait to detect reference-wrapper specializations. More...

Namespaces

namespace  bslmf

Detailed Description

Outline
Purpose:
Provide a trait to detect reference-wrapper specializations.
Classes:
bslmf::IsReferenceWrapper metafunction for detecting reference wrappers
See also:
Component bslstl_referencewrapper
Description:
This component provides a struct template, bslmf::IsReferenceWrapper, that is a boolean metafunction with a single class template parameter t_TYPE. bslmf::IsReferenceWrapper derives from bsl::false_type by default. The only intended specialization of bslmf::IsReferenceWrapper is for bsl::reference_wrapper. Clients are not allowed to specialized bslmf::IsReferenceWrapper for any other type.
This component exists primarily because there are other type traits provided by components in the bslmf package that require the ability to detect whether or not a type is a specialization of bsl::reference_wrapper, notably bsl::invoke_result. bsl::reference_wrapper is defined in the bslstl_referencewrapper component in the bslstl package, and is available to clients through the bsl_functional component in the bsl+bslhdrs package. These packages are levelized above bslmf, and so this trait permits components in the bslmf package (and above) to detect whether or not a type is a reference wrapper even if they cannot refer to the bsl::reference_wrapper type.
Usage:
In this section we show intended use of this component.
Example: Reference Access:
In this example, we suppose that we would like to provide a software component that treats specializations of bsl::reference_wrapper and true reference qualified types in the same way.
Suppose that we would like to do this by having a utility function that returns an lvalue reference to an object given either an lvalue-reference qualified type or a bsl::reference_wrapper.
First, we define a utility struct that contains the overload of this utility function for const and non-'const' lvalue-reference qualified types:
  struct MyLvalueReferenceUtil {
      // CLASS METHODS
      template <class t_TYPE>
      static t_TYPE& access(t_TYPE& reference)
      {
          return reference;
      }

      template <class t_TYPE>
      static const t_TYPE& access(const t_TYPE& reference)
      {
          return reference;
      }
Then, we define the overload of this utility function for reference wrappers, taking care to define it such that it does not participate in overload resolution unless it is passed a reference wrapper:
      template <class t_TYPE>
      static typename bsl::enable_if<
          bslmf::IsReferenceWrapper<t_TYPE>::value,
          typename bsl::add_lvalue_reference<typename t_TYPE::type>::type
      >::type
      access(t_TYPE referenceWrapper)
      {
          return referenceWrapper.get();
      }
  };
Finally, we can verify that this utility allows us to transparently access lvalue references:
  void example()
  {
      int x = 1;
      assert(1 == MyLvalueReferenceUtil::access(x));

      const int y = 2;
      assert(2 == MyLvalueReferenceUtil::access(y));

      // Note that even though the following invokes 'access' with the
      // literal 3, which is a prvalue expression, the call expression is
      // an lvalue with type 'const int&'.
      assert(3 == MyLvalueReferenceUtil::access(3));

      // Further, note that the levelization of the
      // 'bslmf_isreferencewrapper' component prohibits showing the
      // application of 'MyLvalueReferenceUtil' to a reference wrapper.
      // The following commented-out code would be valid given a suitable
      // 'bsl::reference_wrapper' type that acts like a reference wrapper
      // and specializes the 'bslmf::IsReferenceWrapper' trait accordingly.
      //..
      //  assert(x == MyLvalueReferenceUtil::access(
      //                                    bsl::reference_wrapper<int>(x)));
      //..
  }