任何人都有通过继承来减少模板代码膨胀的经验吗?
我犹豫以此方式重写我们的容器:
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& );
//...
};
我应该在减少编译时间的同时保持最佳性能。我也想知道为什么标准库实现不使用这种方法。
如果您不知道所存储元素的类型,那么只有很少的矢量操作才有意义。例如,您添加到基类中的clear()
方法需要调用从向量中移除的元素的析构函数,因此它需要知道其类型并需要进行模板化。
在void *m_rawData
上,如果不知道其内部事物的类型,实际上您也无能为力,基本上,对它的所有操作至少都必须知道存储类型的大小。我唯一能想到的是,如果知道它不包含任何元素(如果它包含必须调用其析构函数的元素),则可以free()
。如果您不知道各个元素的开始和结束位置,则分配,设置和访问元素都将无效。同样,如果将m_rawData
键入为正确的T*
,则所有方法的实现都将更加简洁明了。
基类中的size()
方法仅在其唯一的工作是返回m_size
成员变量时才有效,但是矢量不一定必须显式存储大小(我知道的实现不需要)。您可能可以实现,以便显式存储大小,但是即使size()
还是模板化的,它也可能不是花费很长时间才能编译的方法。
总的来说,我认为尚没有很多可以在基类中实现的方法。向量上的大多数操作都需要了解其中存储的元素。
我认为这是过早的优化。通常,除了嵌入式系统中的磁盘空间和内存外,它们的价格也很便宜,因此没有理由尝试为少量的代码空间进行优化。通过将其全部保留在模板代码中,它使发生的事情更加明显,而不是使用使事情复杂化的继承。
另外,大多数应用程序不会生成数百个实例,并且对于每个T而言,并非所有方法都可以使用,从而进一步减少了代码占用。
[只有在有非常严格的内存注意事项(嵌入式)时,我才会考虑其他可能的方法(包括您提出的方法)。>>
编辑:我不确定在少量标准容器中是否会有很多好处,因为它们仍然需要大量模板代码。对于只有少量模板特定代码和大量通用逻辑的内部类,这无疑可以帮助生成代码和提高编译速度。我怀疑它不经常使用,因为它更复杂并且其好处仅限于某些情况。
我了解您的方法。
do
vectorBase
通过转换为void*
丢失了有关何时调用析构函数的所有信息。为了正确执行此操作,调用正确的析构函数,您需要生成每个调用正确的析构函数的代码的不同副本,并且使用模板可以简化此工作。