将模板类更改为常规类- c++

Changing a template class to a regular class - C++

本文关键字:常规类 c++      更新时间:2023-10-16

我有一个模板类:

template<typename T>
class A {
public:
 virtual void func(T t);
 virtual void func2(T t);
 .
 .
 .
 virtual void funcN(T t);
}

基本上很多类都继承自a,但T总是B或c两种类型之一。

当前我在类中所做的每一个更改都会导致一个很长的构建。

因为T可以是B也可以是C,所以我想把这个类变成一个普通的类。

有什么想法如何在一个聪明的和干净的方式做这个改变,而不复制每个函数两次?

谢谢

最简单的解决方案可能是使用显式特化。您保留模板,但要显式地告诉编译器为哪些类实例化它。

将包含class A的头文件更改为仅包含类及其成员的声明(就像您对常规类所做的那样)。然后用A的成员函数和显式专门化的实现创建一个文件A.cpp,像这样

#include <A.h>
#include <B.h>
#include <C.h>
//... Implementation of A
template class A<B>; // explicit instantiation for B
template class A<C>; // and for C

并将此文件添加到您的项目中。

如果不使用诸如使用预处理器来定义模板类的共享部分之类的技巧,那么如果不引入一些代码复制,就无法避免使用模板。

如果BC没有共同的祖先,您可以为A<B>A<C>引入非模板类,并从它们继承,如下所示:

class AofB : public A<B> {};
class AofC : public A<C> {};
class SomeClass1 : public AofB { // this used to be A<B>
    ...
};
class SomeClass2 : public AofC { // this used to be A<C>
    ...
};

但是,这不太可能改变编译的速度。

如果BC确实有很多共同的功能,可以考虑制作一个非模板版本的A,它可以多态地使用BC的共同祖先。然而,这可能并不总是理想的,因为它将迫使您在模板参数T的实例之前已经足够的地方使用指针/引用。

一种可能性是让BC从一个共同的基类派生,并让A操作指向该基类的指针或引用:

class base {};
class B : public base {};
class C : public base {};
class A {
public:
    virtual void func(base &b);
    virtual void func2(base &b);
    // ...
    virtual void funcN(base &b);
};

这个避免由于A的更改而重新编译B和C——但是在运行时要付出一些额外的代价。具体来说,A必须通过指针或引用来处理B和C对象,这会带来一些开销。

如果我没看错的话,你真正的问题是"我如何在使用这个模板类的时候缩短构建时间",而不是"我如何去模板这个类"。

最有可能的问题源于必须重新编译所有文件,而不是模板实例化,但即使如此,想到的最明显的解决方案(考虑到A的虚函数同时使用BC对象作为参数)是从编译时改为运行时多态性。

引入BC共同的基类,然后A不需要被模板化,它可以简单地接受指向BC_Parent对象的指针/引用,利用共同的接口来完成所需的工作。这将有助于立即节省编译时间,但是如果希望节省更多的时间,您现在可以使用pimpl模式进一步将您的更改与使用它们的客户机类隔离开来。

在任何情况下,当A的实际接口发生变化时,都不能避免完全重新编译。