Provide a template metafunction that returns its argument.
More...
Detailed Description
- Outline
-
-
- Purpose:
- Provide a template metafunction that returns its argument.
-
- Classes:
-
-
- 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) { }
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));
TestType v2(implicitCastNAIVE<TestType>("bye"));
TestType v3(implicitCastNAIVE("hello"));
Now, we implement implicitCast
correctly, using bsl::type_identity
to prevent implicit template-argument deduction: 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));
TestType v5(implicitCast<TestType>("bye"));
TestType v6(implicitCast("hello"));
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);
double d1 = twoThirdsOfTheWay1(0, 0.75);
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);
double d2 = twoThirdsOfTheWay(0, 0.75);
Finally, we verify that our twoThirdsOfTheWay
function worked correctly: int main()
{
assert(4 == i2);
assert(0.5 == d2);
assert(0 == twoThirdsOfTheWay(4U, -2));
}