16.2.2. Function-Template Explicit Arguments

Image

In some situations, it is not possible for the compiler to deduce the types of the template arguments. In others, we want to allow the user to control the template instantiation. Both cases arise most often when a function return type differs from any of those used in the parameter list.

Specifying an Explicit Template Argument

As an example in which we want to let the user specify which type to use, we’ll define a function template named sum that takes arguments of two different types. We’d like to let the user specify the type of the result. That way the user can choose whatever precision is appropriate.

We can let the user control the type of the return by defining a third template parameter to represent the return type:

// T1 cannot be deduced: it doesn't appear in the function parameter list
template <typename T1, typename T2, typename T3>
T1 sum(T2, T3);

In this case, there is no argument whose type can be used to deduce the type of T1. The caller must provide an explicit template argument for this parameter on each call to sum.

We supply an explicit template argument to a call the same way that we define an instance of a class template. Explicit template arguments are specified inside angle brackets after the function name and before the argument list:

// T1 is explicitly specified; T2 and T3 are inferred from the argument types
auto val3 = sum<long long>(i, lng); // long long sum(int, long)

This call explicitly specifies the type for T1. The compiler will deduce the types for T2 and T3 from the types of i and lng.

Explicit template argument(s) are matched to corresponding template parameter(s) from left to right; the first template argument is matched to the first template parameter, the second argument to the second parameter, and so on. An explicit template argument may be omitted only for the trailing (right-most) parameters, and then only if these can be deduced from the function parameters. If our sum function had been written as

// poor design: users must explicitly specify all three template parameters
template <typename T1, typename T2, typename T3>
T3 alternative_sum(T2, T1);

then we would always have to specify arguments for all three parameters:

// error: can't infer initial template parameters
auto val3 = alternative_sum<long long>(i, lng);
// ok: all three parameters are explicitly specified
auto val2 = alternative_sum<long long, int, long>(i, lng);

Normal Conversions Apply for Explicitly Specified Arguments

For the same reasons that normal conversions are permitted for parameters that are defined using ordinary types (§ 16.2.1, p. 680), normal conversions also apply for arguments whose template type parameter is explicitly specified:

long lng;
compare(lng, 1024);       // error: template parameters don't match
compare<long>(lng, 1024); // ok: instantiates compare(long, long)
compare<int>(lng, 1024);  // ok: instantiates compare(int, int)

As we’ve seen, the first call is in error because the arguments to compare must have the same type. If we explicitly specify the template parameter type, normal conversions apply. Thus, the call to compare<long> is equivalent to calling a function taking two const long& parameters. The int parameter is automatically converted to long. In the second call, T is explicitly specified as int, so lng is converted to int.


Exercises Section 16.2.2

Exercise 16.37: The library max function has two function parameters and returns the larger of its arguments. This function has one template type parameter. Could you call max passing it an int and a double? If so, how? If not, why not?

Exercise 16.38: When we call make_shared12.1.1, p. 451), we have to provide an explicit template argument. Explain why that argument is needed and how it is used.

Exercise 16.39: Use an explicit template argument to make it sensible to pass two string literals to the original version of compare from § 16.1.1 (p. 652).


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.249.174