0

我有一个专门用于特定类型的函数模板。在某些情况下,我无法调用专用版本。为了显示

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

我不明白为什么——在第三次调用中,“Foo”不会像直接调用时那样调用 FooInternal 的专用版本。在这种情况下,编译器不应该理解它是从“Base”派生的吗?我在这里缺少什么规则?

如果这很重要,我正在使用 Microsoft Visual Studio 2012 Update 3。

-乔

4

1 回答 1

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);
}

这应该可以为您提供所需的内容(在所有编译器上)。

于 2013-07-18T22:15:40.480 回答