Quick Links:

bal | bbl | bdl | bsl

Classes

Component bslmf_typeidentity
[Package bslmf]

Provide a template metafunction that returns its argument. More...

Classes

struct  bsl::type_identity< t_TYPE >

Detailed Description

Outline
Purpose:
Provide a template metafunction that returns its argument.
Classes:
bsl::type_identity template metafunction that returns its argument.
bsl::type_identity_t alias for the return type of type_identity
Macros:
BSLMF_TYPEIDENTITY_T Macro equivalent to bsl::type_identity_t for C++03
See also:
Description:
This component provides a trivial template metafunction class, bsl::type_identity that takes one type template argument and produces the argument type as its result; i.e., bsl::type_identity<t_TYPE>type is simply an alias for t_TYPE. This metafunction is used in situations where a no-op metafunction is desired or where template type deduction should be suppressed. This component also provides, for C++11 and later, an alias, bsl::type_identity_t such that bsl::type_identity_t<t_TYPE> is short hand for typename bsl::type_identity<t_TYPE>type.
The templates in this component have identical functionality to the standard templates, std::type_identity and std::type_identity_t defined in the <type_traits> header starting with C++20.
Usage:
Example 1: Requiring explicit function template arguments:
A function template can often deduce the types of its arguments, but sometimes we wish to prevent such deduction and require the user to supply the desired type explicitly. In this example, we'll declare a cast function, implicitCast, that is invoked implicitCast<T>(arg). The goal is cast the arg to type T, but only if arg is implicitly convertible to T.
First, we'll define a type TestType, that is implicitly convertible from int but only explicitly convertible from const char *:
  struct TestType {
      TestType(int) { }                                           // IMPLICIT
      explicit TestType(const char*) { }
  };
Next, we'll define implicitCastNAIVE, a naive and insufficient attempt at defining implicitCast:
  template <class t_TYPE>
  t_TYPE implicitCastNAIVE(t_TYPE arg)
  {
      return arg;
  }
Next, we try to use implicitCastNAIVE. The first invocation below correctly casts an int to TestType. The second invocation should, and does, fail to compile because const char* is not implicitly convertible to TestType. In the third invocation, we forgot the <TestType> template parameter. Surprisingly (for the user), the code compiles anyway because implicitCastNAIVE deduced t_TYPE to be const char* and returns its argument unmodified, i.e., doing no casting whatsoever:
  TestType v1(implicitCastNAIVE<TestType>(5));      // OK
  TestType v2(implicitCastNAIVE<TestType>("bye"));  // Fails correctly.
  TestType v3(implicitCastNAIVE("hello"));          // Succeeds incorrectly.
Now, we implement implicitCast correctly, using bsl::type_identity to prevent implicit template-argument deduction:
  template <class t_TYPE>
  t_TYPE implicitCast(typename bsl::type_identity<t_TYPE>::type arg)
  {
      return arg;
  }
Finally, we try using implicitCast both correctly and incorrectly. As before, the first invocation below correctly casts an int to TestType and second invocation correctly fails to compile. Unlike the implicitCastNAIVE example, however, the third invocation correctly fails to compile because t_TYPE is not deduceable for a parameter of type bsl::type_identity<t_TYPE>type.
  TestType v4(implicitCast<TestType>(5));      // OK
  TestType v5(implicitCast<TestType>("bye"));  // Fails correctly.
  TestType v6(implicitCast("hello"));          // Fails correctly.
Note that typename bsl::type_identity<t_TYPE>type can be replaced by the more concise bsl::type_identity_t<t_TYPE> (compatible with C++11 and later) or BSLMF_TYPEIDENTITY_T(t_TYPE) (compatible with all C++ versions).
Example 2: preventing ambiguous argument deduction in function templates:
In this example, we illustrate how to prevent ambiguities when type deductions occurs on multiple function-template arguments. Our sample function returns a number within a range two-thirds of the way between the start and end of the range. The types of the arguments determine the type of the result.
First, we implement the function using a simple but potentially ambiguous interface:
  template <class NUMTYPE>
  inline NUMTYPE twoThirdsOfTheWay1(NUMTYPE first, NUMTYPE last)
  {
      return first + (last - first) * 2 / 3;
  }
Now, try to invoke our function. We get into trouble when the two arguments have different types; the compiler is unable to deduce a single NUMTYPE:
  int i1 = twoThirdsOfTheWay1(0, 6);        // OK, 'NUMTYPE' is 'int'
  double d1 = twoThirdsOfTheWay1(0, 0.75);  // Ambiguous: 'int' vs 'double'
Next, we try again, this time using bsl::type_identity to suppress type deduction on the first argument. The first argument, rather than the second argument is chosen for this treatment because the first argument of a numeric range is so often 0, which happens to be an int but is often used, without losing precision, with unsigned, float, and double values. The second argument, conversely, usually carries a significant value whose type is important:
  template <class NUMTYPE>
  inline NUMTYPE twoThirdsOfTheWay(BSLMF_TYPEIDENTITY_T(NUMTYPE) first,
                                   NUMTYPE                       last)
  {
      return first + (last - first) * 2 / 3;
  }

  int i2 = twoThirdsOfTheWay(0, 6);        // OK, 'NUMTYPE' is 'int'
  double d2 = twoThirdsOfTheWay(0, 0.75);  // OK, 'NUMTYPE' is 'double'
Finally, we verify that our twoThirdsOfTheWay function worked correctly:
  int main()
  {
      assert(4 == i2);
      assert(0.5 == d2);
      assert(0 == twoThirdsOfTheWay(4U, -2));
  }