C++ 模版参数推断

C++模板参数推断是根据函数参数类型确定模板参数的过程。如果模板参数被用作多个函数参数类型,所有对应参数类型必须完全匹配。不匹配会导致错误。如果允许参数类型兼容,可以使用两个类型参数来定义模板。对于不匹配的类型,如数组或函数到指针的转换,编译器不会尝试匹配现有实例,而是生成新实例。特殊情况包括常量转换和数组或函数到指针的转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

16.2.1. Template Argument Deduction

To determine which functions to instantiate, thecompiler looks at each argument. If the corresponding parameter wasdeclared with a type that is a type parameter, then the compiler infersthe type of the parameter from the type of the argument. In the case of compare, both arguments have the same template type: they were eachdeclared using the type parameter T.

Inthe first call, compare(1, 0), those arguments are type int; in the second,compare, they have type double. The process of determining the types andvalues of the template arguments from the type of the function argumentsis called template argument deduction .

 

MultipleType Parameter Arguments Must Match Exactly

A template type parameter may be used as the type of more than one functionparameter. In such cases, template type deduction must generate the sametemplate argument type for each corresponding function argument. If thededuced types do not match, then the call is an error:


template <typename T>
int compare(const T& v1, const T& v2)
{
if (v1 < v2) return -1;
if (v2 < v1) return 1;
return 0;
}
int main()
{
short si;
// error: cannot instantiate compare(short, int)
// must be: compare(short, short) or
// compare(int, int)
compare(si, 1024);
return 0;
}


This call is in error because the arguments to comparedon't have the same type.The template argument deduced from the first argument is short; the onefor the second is int. These types don't match, so template argumentdeduction fails.
If the designer of comparewants to allow normal conversions on the arguments,then the function must be defined with two type parameters:


// argument types can differ, but must be compatible
template <typename A, typename B>
int compare(const A& v1, const B& v2)
{
if (v1 < v2) return -1;
if (v2 < v1) return 1;
return 0;
}


Now the user may supply arguments of different types:
short si;
compare(si, 1024); // ok: instantiates compare(short, int)


However, a <operator must exist that can compare values of those types.

 

LimitedConversions on Type Parameter Arguments

LimitedConversions on Type Parameter Arguments
Consider the following calls to compare:
short s1, s2;
int i1, i2;
compare(i1, i2); // ok: instantiate compare(int, int)
compare(s1, s2); // ok: instantiate compare(short, short)


The first call generates an instance of comparewith Tbound to int. A newinstance is created
for the second call, binding Tto short.


Had compare(int, int)been an ordinary nontemplate function, then the secondcall would
match that function. The shortarguments would be promoted (Section 5.12.2, p.180) to int.
Because compareis a template, a new function is instantiated with the typeparameter bound to
short.


In general, arguments are not converted to match an existing instantiation;instead, a new instance is generated. There are only two kinds of conversions that thecompiler will perform rather than generating a new instantiation:

const conversions: A function that takes a reference or pointer to a constcan becalled with a reference or pointer to nonconstobject, respectively, without generatinga new instantiation. If the function takes a nonreference type, then constis ignoredon either the parameter type or the argument. That is, the same instantiation will be usedwhether we pass a constor nonconstobject to a function defined to take a nonreferencetype. 

array or function to pointer conversions:If the template parameter is not areference type, then the normal pointer conversion will be applied to arguments of array orfunction type. An array argument will be treated as a pointer to its first element, and afunction argument will be treated as a pointer to the function's type.


As examples, consider calls to the functions fobjand fref. The fobjfunctioncopies its
parameters, whereas fref's parameters are references:


template <typename T> T fobj(T, T); // arguments are copied
template <typename T>
T fref(const T&, const T&); // reference arguments
string s1("a value");
const string s2("another value");
fobj(s1, s2); // ok: calls f(string, string), const is ignored
fref(s1, s2); // ok: non const object s1 converted to const reference
int a[10], b[42];
fobj(a, b); // ok: calls f(int*, int*)
fref(a, b); // error: array types don't match; arguments aren't converted topointers


In the first case, we pass a stringand a const stringas arguments. Even thoughthese types do not match exactly, both calls are legal. In the call to fobj, the argumentsare copied, so whether the original object is constdoesn't matter. In the call to fref, theparameter type is a reference to const. Conversion to constfor a reference parameter is one of theacceptable conversions, so this call is also okay.
In the next case, we pass array arguments in which the arrays are differentsizes. In the call to fobj, the fact that the arrays are different doesn't matter. Both arrays areconverted to pointers. The template parameter type in fobjis int*. The call to fref,however, is illegal. When the parameter is a reference (Section 7.2.4, p. 240), the arrays are notconverted to pointers. The types of aand bdon't match, so the call is in error.

 

Template Argument Deduction and Function Pointers

We can use a function template to initialize or assign to a function pointer (Section 7.9, p. 276 ). When we do so, the compiler uses the type of the pointer to instantiate a version of the template with the appropriate template argument(s).

As an example, assume we have a function pointer that points to a function returning an int that takes two parameters, each of which is a reference to a const int. We could use that pointer to point to an instantiation of compare: 


template <typename T> int compare(const T&, const T&);
// pf1 points to the instantiation int compare (const int&, const int&)
int (*pf1) (const int&, const int&) = compare;


The type of pf1is "pointer to function returning an  inttaking two parameters of type const int&." The type of the parameters in pf1determines the type of the template argument for T. The template argument for Tis int. The pointer pf1refers to the instantiation with Tbound to int.


It is an error if the template arguments cannot be determined from the function pointer type. For example, assume we have two functions named func. Each function takes a pointer to function argument. The first version of functakes a pointer to a function that has two const stringreference parameters and returns a string. The second version of functakes a pointer to a function taking two const intreference parameters and returning an int. We cannot use compareas an argument to func:


// overloaded versions of func; each take a different function pointer type
void func(int(*) (const string&, const string&));
void func(int(*) (const int&, const int&));
func(compare); // error: which instantiation of compare?


The problem is that by looking at the type of func's parameter, it is not possible to determine a unique type for the template argument. The call to funccould instantiate either of the following functions:


compare(const string&, const string&)
compare(const int&, const int&)
Because it is not possible to identify a unique instantiation for the argument to func, this call is a  compile-time (or link-time) error.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值