C++模板函数实例化代码大小

C++ Template Function Instantiation Code Size

本文关键字:代码 实例化 函数 C++      更新时间:2023-10-16

我试图减少模板函数实例化的数量,但遇到了一个障碍。

假设我们有以下类(我知道它没有优化:这是故意说明问题的):

//class no_inherit is implemented the same way as class base (below). 
//This is done to illustrate the issue I'm seeing.
template<typename T, size_t SIZE>
class no_inherit
{
private:
    T m_data[SIZE];
    const size_t m_size;
public:
    no_inherit() :m_size(SIZE){}
    T& operator[](size_t i)
    {return m_data[i];}
    inline size_t size() const
    {return m_size;}
}; 

以下功能:

template<typename T>
void huge_func(T& v)
{
    //..do lots of stuff with v.  For example
    for(size_t i = 0; i < v.size(); ++i)
        v[i] = v[i] + i;
    //...do lots more with v
}

和以下代码:

int main()
{
    no_inherit<int, 4> v1;
    no_inherit<int, 2> v2;
    huge_func(v1);
    huge_func(v2);
}

huge_func()将被实例化两次:

void huge_func(no_inherit<int, 4>& v);
void huge_func(no_inherit<int, 2>& v);

由于huge_func()是巨大的,我试图通过创建以下类层次结构来减少实例化次数,方法是获取其中一个模板参数并将其转换为动态参数:

//Base class only has 1 template parameter.
template<typename T>
class base
{
private:
    T *m_data;  
    const size_t m_size; //hold child's templated size parameter.
protected:
    inline base(T* data, size_t size): m_data(data), m_size(size){}
public:
    T& operator[](size_t i)
    {return m_data[i];}
    inline size_t size() const
    {return m_size;}
};
//Child class has two template parameters
template<typename T, size_t SIZE>
class inherit: public base<T>
{
private:    
    T m_data[SIZE];
public:
    //Pass template parameter to base class
    inherit() : base<T>(m_data, SIZE){}
};

我调用huge_func()如下:

int main()
{
    inherit<int, 4> v1;
    inherit<int, 2> v2;
    //make sure only one instantiation of huge_func() is made
    //by using the same type.
    base<int> &v1b = v1;
    base<int> &v2b = v2;
    huge_func(v1b); 
    huge_func(v2b);
}

这只会实例化一个huge_func()函数:

void huge_func(base<int>& v);

因此将减小代码大小。

但是ALAS!当我使用类层次结构时,代码大小会增加。这怎么可能?

如果我有以下代码,那就更奇怪了。

int main()
{
    inherit<int, 4> v1;
    inherit<int, 2> v2;
    huge_func(v1);
    huge_func(v2);
}

代码大小与调用huge_fonc(v1b)和huge_focc(v2b)相同。

编译器在做什么?

首先,如果huge_func确实是"巨大的",您可能会从将其拆分为几个可重用的较小函数中受益。

除此之外,您还可以将其模板化:

template<typename T, int SIZE> void huge_func(no_inherit<T, SIZE>& v)
{
    // function implementation goes here
}

然后实现一次,并维护您的平面类结构。