通过继承减少模板膨胀

问题描述 投票:10回答:7

任何人都有通过继承来减少模板代码膨胀的经验吗?

我犹豫以此方式重写我们的容器:

class vectorBase
{
  public:
    int size();
    void clear();
    int m_size;
    void *m_rawData;
    //....
};

template< typename T > 
class vector : public vectorBase
{
    void push_back( const T& );
    //...

};

我应该在减少编译时间的同时保持最佳性能。我也想知道为什么标准库实现不使用这种方法。

c++ inheritance templates code-generation
7个回答
3
投票

如果您不知道所存储元素的类型,那么只有很少的矢量操作才有意义。例如,您添加到基类中的clear()方法需要调用从向量中移除的元素的析构函数,因此它需要知道其类型并需要进行模板化。

void *m_rawData上,如果不知道其内部事物的类型,实际上您也无能为力,基本上,对它的所有操作至少都必须知道存储类型的大小。我唯一能想到的是,如果知道它不包含任何元素(如果它包含必须调用其析构函数的元素),则可以free()。如果您不知道各个元素的开始和结束位置,则分配,设置和访问元素都将无效。同样,如果将m_rawData键入为正确的T*,则所有方法的实现都将更加简洁明了。

基类中的size()方法仅在其唯一的工作是返回m_size成员变量时才有效,但是矢量不一定必须显式存储大小(我知道的实现不需要)。您可能可以实现,以便显式存储大小,但是即使size()还是模板化的,它也可能不是花费很长时间才能编译的方法。

总的来说,我认为尚没有很多可以在基类中实现的方法。向量上的大多数操作都需要了解其中存储的元素。


1
投票

我认为这是过早的优化。通常,除了嵌入式系统中的磁盘空间和内存外,它们的价格也很便宜,因此没有理由尝试为少量的代码空间进行优化。通过将其全部保留在模板代码中,它使发生的事情更加明显,而不是使用使事情复杂化的继承。

另外,大多数应用程序不会生成数百个实例,并且对于每个T而言,并非所有方法都可以使用,从而进一步减少了代码占用。

[只有在有非常严格的内存注意事项(嵌入式)时,我才会考虑其他可能的方法(包括您提出的方法)。>>

编辑:我不确定在少量标准容器中是否会有很多好处,因为它们仍然需要大量模板代码。对于只有少量模板特定代码和大量通用逻辑的内部类,这无疑可以帮助生成代码和提高编译速度。我怀疑它不经常使用,因为它更复杂并且其好处仅限于某些情况。


1
投票

我了解您的方法。


1
投票
某些实现

do


0
投票
[IIRC,Qt对他们的QList等使用(或使用?)类似的方法。

0
投票
您发布的代码是完全错误的。如果要存储在向量中的类具有析构函数,则不会调用该析构函数,因为编译器vectorBase通过转换为void*丢失了有关何时调用析构函数的所有信息。

为了正确执行此操作,调用正确的析构函数,您需要生成每个调用正确的析构函数的代码的不同副本,并且使用模板可以简化此工作。


0
投票
它的缩写:
© www.soinside.com 2019 - 2024. All rights reserved.