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

时间:2012-12-26 16:09:41

标签: c++ templates

我有一个模板类:

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 个答案:

答案 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,例如使用预处理器来定义你想要的模板类的共享部分,你就无法避免模板而不引入一些代码重复。

如果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和{{的共同祖先的B非模板版本1}}多态的。但是,这可能并不总是可取的,因为它会强制您使用指针/引用,其中模板参数C的实例在此之前就已足够了。

答案 2 :(得分: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对象,这会带来一些开销。

答案 3 :(得分:1)

如果我正确读到这一点,那么您真正的问题是“如何在使用此模板类时缩短构建时间”,而不是“如何对此类进行去模板化”。

问题很可能源于必须重新编译所有文件而不是模板实例化,但即使如此,最明显的解决方案也会浮现在脑海中(假设A的虚拟函数同时适用于BC对象作为参数)是从编译时更改为运行时多态。

引入一个与BC共同的基类,然后代替A需要进行模板化,它可以简单地接受指向BC_Parent的指针/引用相反,使用通用接口来完成所需的工作。这应该会立即帮助编译时间,但如果需要更多节省,您现在可以使用pimpl模式进一步将更改与使用它们的客户端类隔离开来。

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