在2个模板参数中的下面的代码中,我使用其中一个隐式和另一个显式:
class A {};
template<typename ToType, typename FromType>
ToType CompileTimeCast (FromType pointer)
{
return (ToType)(pointer);
}
int main ()
{
A *pA;
int *pi = CompileTimeCast<int*>(pA); // function invocation
}
工作正常。现在,如果我在参数列表中交换ToType
和FromType
,编译器会抛出错误:
error: no matching function for call to ‘CompileTimeCast(A*&)’
很奇怪,为什么编译器在知道函数调用时两个参数都不同而且已经使用了一个参数时会抱怨?
答案 0 :(得分:3)
当您明确指定模板参数时,您必须按顺序指定它们,就像您必须以正确的顺序指定函数参数一样,即使它们是默认的:
int *pi = CompileTimeCast<int*, const int*>(pA);
在此示例中,假设您的原始代码,ToType
为int*
且FromType
为const int*
。如果只显式指定模板参数的子集,则编译器必须按顺序假设您的子集是前几个模板参数。 所有尾随模板参数必须可以推断。
请注意,对于编译器推导出的模板参数集,顺序无关紧要。在您的示例中,仅 FromType
是可以推断的。
您已经发现了对模板参数进行排序的正确理由:通过降低客户希望在函数调用中明确指定它们的概率来对它们进行排序。
答案 1 :(得分:2)
如果你的意思是交换:
template<typename FromType, typename ToType> //argument swapped their position!
ToType CompileTimeCast (FromType pointer)
然后论证推论将不再起作用。因为当你编写CompileTimeCast<int*>
时,编译器会认为int*
始终是函数模板参数列表中的第一个参数。第二个参数将由编译器推导出来。
现在,您必须明确提及以下类型:
int *pi = CompileTimeCast<A*, int*>(pA); //FromType=A*, ToType=int*
答案 2 :(得分:0)
编译器应该能够使用函数调用签名来确定返回值的类型,而不是使用任何变量。