我有一个模板类:
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,我想将类转换为常规类。
任何想法如何以智能和干净的方式进行更改,而无需复制每个功能两次?
由于
答案 0 :(得分:7)
最简单的解决方案可能是使用显式特化。保留模板,但是明确地告诉编译器要实例化哪些类。
更改包含class A
的头文件,使其仅包含类及其成员的声明(就像您对常规类所做的那样)。然后创建一个文件A.cpp
,其中包含A
的成员函数的实现和显式特化,如下所示
#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
并将此文件添加到您的项目中。
答案 1 :(得分:2)
不使用hacks,例如使用预处理器来定义你想要的模板类的共享部分,你就无法避免模板而不引入一些代码重复。
如果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
非模板版本1}}多态的。但是,这可能并不总是可取的,因为它会强制您使用指针/引用,其中模板参数C
的实例在此之前就已足够了。
答案 2 :(得分:1)
一种可能性是让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对象,这会带来一些开销。
答案 3 :(得分:1)
如果我正确读到这一点,那么您真正的问题是“如何在使用此模板类时缩短构建时间”,而不是“如何对此类进行去模板化”。
问题很可能源于必须重新编译所有文件而不是模板实例化,但即使如此,最明显的解决方案也会浮现在脑海中(假设A
的虚拟函数同时适用于B
和C
对象作为参数)是从编译时更改为运行时多态。
引入一个与B
和C
共同的基类,然后代替A
需要进行模板化,它可以简单地接受指向BC_Parent
的指针/引用相反,使用通用接口来完成所需的工作。这应该会立即帮助编译时间,但如果需要更多节省,您现在可以使用pimpl模式进一步将更改与使用它们的客户端类隔离开来。
当A
的实际界面发生变化时,在任何情况下都不能避免完全重新编译。