我有一个专门针对特定类型的功能模板。在某些情况下我无法调用专用版本。为了说明
struct Base {};
struct Derived : public Base {};
template <typename VALTYPE> void FooInternal(VALTYPE&)
{
std::cout << L"FooInternal template";
}
template<> void FooInternal(Base&)
{
std::cout << L"FooInternal SPECIAL";
}
现在,如果我构建一个“Base”或“Derived”的实例并调用“FooInternal”,那么所有的工作都如我所料
int _tmain(int argc, _TCHAR* argv[])
{
int x = 7;
FooInternal(x); // Calls FooInternal<VALTYPE>() template
Base b;
FooIntenral(b); // Calls FooInternal<Base>() specialization
Derived d;
FooInternal(d); // Calls FooInternal<Base>() specialization
return 0;
}
这是
的输出FooInternal template
FooInternal SPECIAL
FooInternal SPECIAL
}
但是假设我在这两者之间有一个调用FooInternal的中间函数模板。在这种情况下,派生类型的模板分辨率似乎在路上失败
// Intermediate template. Just calls FooInternal.
template<typename VALTYPE>
void Foo(VALTYPE& val)
{
FooInternal<VALTYPE>(val);
}
// Now repeat the same 3 calls and see what happens with Derived...
int _tmain(int argc, _TCHAR* argv[])
{
int x = 7;
Foo(x); // Calls FooInternal<VALTYPE>() template
Base b;
Foo(b); // Calls FooInternal<Base>() specialization
Derived d;
Foo(d); // Calls FooInternal<VALTYPE>() template!!!
return 0;
}
该程序的输出是
FooInternal template
FooInternal SPECIAL
FooInternal template
我无法理解为什么 - 在第3次调用中,“Foo”将不会调用FooInternal的专用版本,就像调用是直接调用时一样。编译器是否应该理解在这种情况下从'Base'派生出来?我在这里错过了什么规则?
我正在使用Microsoft Visual Studio 2012 Update 3,如果这很重要。
-Joe
答案 0 :(得分:1)
您在第一个示例中的期望,显然也是您的编译器,是错误的。输出应为“FooInternal templateFooInternal SPECIALFooInternal模板”。
函数模板特化对模板参数推导或重载解析没有任何作用。只有在没有查看规则的情况下,才能使用完全相同的模板参数。
大多数情况下,当您认为自己需要函数模板专业化时,最好重新设置函数(使用其他模板或使用非模板)。
inline void FooInternal(Base&)
{
std::cout << L"FooInternal SPECIAL";
}
当然,如果您指定模板参数,则永远不会调用FooInternal
,因此您需要:
// Intermediate template. Just calls FooInternal.
template<typename VALTYPE>
void Foo(VALTYPE& val)
{
FooInternal(val);
}
这可以让你得到你想要的东西(在所有编译器上)。