templateでクラスの大きさを指定する方法

C++でクラスを作るときにsizeofで帰ってくる大きさを自由に決められるようにしたいなぁと思ったのでやり方を調べてみました。

まず、普通のint型みたいなものの大きさを変更する方法からです。これには__declspec(align(#))装飾子を使います。

// sizeof(Int4) == 4
struct Int4 { int n; }; 

// sizeof(Int8) == 8 (Visual C++)
__declspec(align(8)) struct Int8 { int n }; 

// sizeof(Int8) == 8 (g++)
__attribute__((aligned(8))) struct Int8 { int n }; 

で、このalignサイズをtemplateで指定できないかな、と考えるわけです。

結論から言うと、普通にtemplate宣言にalignを追加するだけではだめで、templateの特殊化を使う必要があります。

// original template
template <class Ty, int Sz> class Array
{
public:
    Ty *data;
    Array() : data(0)
    {
        data = new Ty[Sz];
    }

    ~P()
    {
        delete[] data;
    }
};

// specialized template
template<> class __declspec(align(32)) Array<int,4> 
{
public:
    int data[4];
    Array() : data()
    {
    }

    ~Array()
    {
    }
};

上の普通のテンプレートはポインタ1つの型ですから、32bit環境なら4byte、64bit環境なら8byteになります。

一方、下の特殊化されたクラスは通常intが4つ分で16byteになりますが、sizeofすると戻ってくる値は32になります。

まぁ、結局、サイズを指定するには特殊化で1つ1つ個別指定が必要なわけですが、厳密に大きさを指定したい場合には使える方法です。