ここでは、作成しようとしているプールされたオブジェクトの最小の実例を示します(明らかに機能は完全ではありません -static class templateメンバ:不完全な型の 'sizeof'の無効なアプリケーション
:それからoperator new
を用いたテンプレートパラメータ
T
の静的クラスメンバーのうち割り当てる基本クラステンプレート
PoolObj
を有する
template<typename T, std::size_t N>
struct Storage
{
std::aligned_storage_t<sizeof(T), alignof(T)> data[N];
};
:私はaligned_storage
を含むクラステンプレートStorage
を有する)を有する
mは
template<typename T>
struct PoolObj
{
static void* operator new(std::size_t size)
{
std::cout << "new T\n";
return &T::pool.data[0];
}
static void operator delete(void* p, std::size_t size)
{
std::cout << "delete T\n";
}
};
今私はPoolObj
から継承するクラスを持っている、と私はnew
を使用してインスタンスを作成するとき、私はプールからストレージを取得するように、静的Storage
メンバーpool
を持っています。
struct Foo : PoolObj<Foo>
{
static Storage<Foo, 10> pool;
};
Storage<Foo, 10> Foo::pool {};
このすべてが正常に動作します:
template<typename T>
struct Bar : PoolObj<Bar<T>>
{
static Storage<Bar<T>, 10> pool;
};
template<typename T>
Storage<Bar<T>, 10> Bar<T>::pool {};
:
int main()
{
Foo* f = new Foo();
delete f;
return 0;
}
今
$ ./a.out new T delete T
が、しかし、私は今PoolObj
がクラステンプレートを有効にしようとしています
これは私が次のエラーを取得するコンパイルしようとすると
int main()
{
Bar<int>* b = new Bar<int>();
delete b;
return 0;
}
を動作しません:
In instantiation of ‘struct Storage<Bar<int>, 10ul>’: required from ‘struct Bar<int>’ error: invalid application of ‘sizeof’ to incomplete type ‘Bar<int>’ std::aligned_storage_t<sizeof(T), alignof(T)> data[N];
- はなぜ
Foo
のための完全なStorage
でT
ですが、Bar<int>
らのために不完全な? - 私がここで望んでいるデザインを達成することは可能でしょうか?以下
#include <type_traits>
#include <cstddef>
template<typename T, std::size_t N>
struct Storage
{
std::aligned_storage_t<sizeof(T), alignof(T)> data[N];
};
template<typename T>
struct PoolObj
{
static void* operator new(std::size_t size)
{
return &T::pool.data[0];
}
static void operator delete(void* p, std::size_t size)
{
}
};
struct Foo : PoolObj<Foo>
{
static Storage<Foo, 10> pool;
};
Storage<Foo, 10> Foo::pool {};
template<typename T>
struct Bar : PoolObj<Bar<T>>
{
static Storage<Bar<T>, 10> pool;
};
template<typename T>
Storage<Bar<T>, 10> Bar<T>::pool {};
int main()
{
Foo* f = new Foo();
delete f;
Bar<int>* b = new Bar<int>();
delete b;
return 0;
}
編集:
興味深いことにthis works fine in clang (coliru)。
- どのコンパイラが正しいですか?
- これはgccのバグですか?
第二編集:
のコメントによると、それはあまりにもVS2017で見つける動作します。そのように、私はgccのバグに傾いていると思いますか?
これは、Barの定義の一部としてBar を使用しているためです。正式な回答にするには十分ではありません。しかし、エラーは理にかなっています。 –
OriBS
コンパイラが 'Bar'の定義中に静的メンバープールのサイズを理解しようとすると、この時点で 'Bar 'は不完全です。プールのサイズを理解するために 'std :: aligned_storage_t 'をチェックすると、 'Bar '(この文脈ではT)はまだ不完全であり、sizeofの不完全な型を取ることは不正です。 –
OriBS
@OriBS 'Storage 012 'は、' Bar 'と宣言したときに、' Bar 'に対してのみインスタンス化されます。それがインスタンス化される時点で、それは完全な型を確実に持っていますか?さらに、それはclangの下で動作します - どのコンパイラが正しいですか? –