制作功能模板专业化虚拟法律?

ale*_*xk7 11 c++ virtual templates specialization c1001

在C++中,函数模板特化应该与正常函数完全相同.这是否意味着我可以制作一个虚拟的?

例如:

struct A
{
    template <class T> void f();
    template <> virtual void f<int>() {}
};

struct B : A
{
    template <class T> void f();
    template <> virtual void f<int>() {}
};

int main(int argc, char* argv[])
{
    B b;
    A& a = b;
    a.f<int>();
}
Run Code Online (Sandbox Code Playgroud)

Visual Studio 2005给出了以下错误:

致命错误C1001:编译器中发生内部错误.

Dav*_*eas 20

编译错误.对于这种类型的检查,我总是回到Comeau编译器,然后再回到标准并检查.

Comeau C/C++ 4.3.10.1(2008年10月6日11:28:09)ONLINE_EVALUATION_BETA2版权所有1988-2008 Comeau Computing.版权所有.MODE:严格错误C++ C++ 0x_extensions

"ComeauTest.c",第3行:错误:函数模板声明模板中不允许"虚拟"虚拟空虚f(); ^

"ComeauTest.c",第10行:错误:函数模板声明模板中不允许"虚拟"虚拟空虚f(); ^

现在,由于它已被另一个用户发布,事实是该标准不允许您定义虚拟模板化方法.基本原理是对于所有虚拟方法,必须在vtable中保留一个条目.问题是模板方法只有在实例化(使用)时才会被定义.这意味着vtable最终会在每个编译单元中拥有不同数量的元素,具体取决于对不同类型的f()进行多少次不同的调用.那么地狱会被提升......

如果你想要的是它的一个参数上的模板化函数和一个虚拟的特定版本(请注意参数的一部分),你可以这样做:

class Base
{
public:
   template <typename T> void f( T a ) {}
   virtual void f( int a ) { std::cout << "base" << std::endl; }
};
class Derived : public Base
{
public:
   virtual void f( int a ) { std::cout << "derived" << std::endl; }
};
int main()
{
   Derived d;
   Base& b = d;
   b.f( 5 ); // The compiler will prefer the non-templated method and print "derived"
}
Run Code Online (Sandbox Code Playgroud)

如果你想要任何类型的广义,那么你运气不好.考虑另一种类型的委托而不是多态(聚合+委派可能是一种解决方案).有关当前问题的更多信息将有助于确定解决方案.

  • 请注意打电话给bf <int>(5); 将生成一个非虚拟的专业化并调用它.因为您使用非模板重载模板,所以调用将更喜欢非模板.但是如果你打电话给bf <int>(5); 它仍将调用非虚函数. (2认同)
  • alexk7,一种简单的方法是类型到类型的包装器:virtual int getv(type_ <int>); virtual bool getv(type_ <bool>); 而type_是模板<typename T> struct type_ {}; 并使用b.getv调用(type_ <T>()); 现在,重载将找出要调用的内容,没有模板,但是使用虚拟:) (2认同)