3

我有一个模板类:

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,我想将班级变成普通班级。

任何想法如何以一种智能和干净的方式进行此更改,而无需复制每个功能两次?

谢谢

4

4 回答 4

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

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

于 2012-12-26T16:28:30.417 回答
2

如果不求助于 hack,例如使用预处理器来定义你的可能模板类的共享部分,你就无法避免模板而不引入一些代码重复。

如果BandC不共享一个共同的祖先,您可以为A<B>and引入非模板类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的共同祖先。但是,这可能并不总是可取的,因为它会迫使您在模板参数的实例之前就足够的情况下使用指针/引用。BCT

于 2012-12-26T16:19:48.350 回答
1

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

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

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

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

于 2012-12-26T20:30:24.560 回答
1

一种可能性是拥有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 对象,这会带来一些开销。

于 2012-12-26T16:20:42.990 回答