0

テンプレート関数のインスタンス化の数を減らそうとしていますが、問題が発生しています。

次のクラスがあるとします (最適化されていないことはわかっています。これは、問題を説明するために意図的に行われています)。

//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() は 2 回インスタンス化されます。

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

huge_func() は非常に大きいため、テンプレート パラメーターの 1 つを取得し、次のクラス階層を作成して動的パラメーターに変換することで、インスタンス化の数を削減しようとしています。

//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);

したがって、コードサイズが減少します。

しかし悲しいかな!クラス階層を使うとコードサイズが大きくなります。これはどのように可能ですか?

次のコードがある場合、さらに奇妙です。

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

    huge_func(v1);
    huge_func(v2);
}

コード サイズは、huge_func(v1b) と huge_func(v2b) を呼び出した場合と同じです。

コンパイラは何をしていますか?

4

1 に答える 1

0

まず第一に、huge_func実際に「巨大」である場合は、再利用可能ないくつかの小さな関数に分割することでメリットが得られる可能性があります。

それはさておき、テンプレート化することもできます:

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

次に、一度実装し、フラットなクラス構造を維持します。

于 2013-08-21T17:33:31.997 に答える