将模板类更改为常规类- c++
Changing a template class to a regular class - C++
我有一个模板类:
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
并将此文件添加到您的项目中。
如果不使用诸如使用预处理器来定义模板类的共享部分之类的技巧,那么如果不引入一些代码复制,就无法避免使用模板。
如果B
和C
没有共同的祖先,您可以为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>
...
};
但是,这不太可能改变编译的速度。
如果B
和C
确实有很多共同的功能,可以考虑制作一个非模板版本的A
,它可以多态地使用B
和C
的共同祖先。然而,这可能并不总是理想的,因为它将迫使您在模板参数T
的实例之前已经足够的地方使用指针/引用。
一种可能性是让B
和C
从一个共同的基类派生,并让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
的虚函数同时使用B
和C
对象作为参数)是从编译时改为运行时多态性。
引入B
和C
共同的基类,然后A
不需要被模板化,它可以简单地接受指向BC_Parent
对象的指针/引用,利用共同的接口来完成所需的工作。这将有助于立即节省编译时间,但是如果希望节省更多的时间,您现在可以使用pimpl模式进一步将您的更改与使用它们的客户机类隔离开来。
在任何情况下,当A
的实际接口发生变化时,都不能避免完全重新编译。
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 具有瞬态资源的RAII类
- 具有默认模板参数的多态类的模板推导失败
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 将二维矢量传递给类
- std::具有相同基类的类的变体
- 命名空间中具有.h和.cpp文件的类
- 在c++中使用nlohmann从类到json的转换
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 在C++中,为什么使用静态类函数而不是常规函数?
- C++ - 模板类专用化是否有办法包含常规模板中的代码
- 是否可以将一个类别的插槽或常规功能从一个类连接到另一个类的插槽或常规功能?(QT)
- 使用Typedef和常规类定义的匿名类定义的等效率
- 将类用于功能而不是使用常规功能是不好的做法吗?
- 如何在不同的类中使用QNetworkAccessManager?类之间重要数据的常规共享
- Boost.Proto:具有自定义终端类的EDSL的常规类布局
- 常规"字符串"类"rwcstring"类之间的区别
- 如何获取常规函数指针作为 C++ 类的私有成员
- 同时具有指针类型和常规类型的类模板
- 将模板类更改为常规类- c++