ほとんどの場合、コンテナの実装の詳細 (より正確には、コンテナ宣言の時点で何がインスタンス化され、何がインスタンス化されないか) に依存します。どうやら、std::unordered_map
実装には型が完全である必要があります。同時に、GCC の実装はstd::map
、不完全な型で完全に問題なくコンパイルされます。
このような違いの原因を説明するために、次の例を検討してください。のような機能の独自の単純な実装を作成することに決めstd::vector
、次のようにベクター クラスを宣言したとしましょう。
template <typename T> class my_vector {
T *begin;
T *end;
...
};
クラス定義に へのポインターのみが含まれている限りT
、型T
はクラス定義自体に対して完全である必要はありません。問題なくmy_vector
不完全なインスタンスを作成できますT
class X;
my_vector<X> v; // OK
型の「完全性」は、後での個々のメソッドを使用する (したがってインスタンス化する) ときに必要になりますmy_vector
。
ただし、何らかの理由で の直接インスタンスをT
ベクター クラスに含めることにした場合、事態は変化します。
template <typename T>
class my_vector {
T *begin;
T *end;
T dummy_element;
...
};
の完全性は、それ自体T
のインスタンス化の時点で、非常に早い段階で必要になります。my_vector
class X;
my_vector<X> v; // ERROR, incomplete type
あなたの場合、そのようなことが起こっているに違いありません。unordered_map
あなたが扱っているの定義には、何らかの形で の直接インスタンスが含まれていますA
。これが、インスタンス化が不可能な理由です (明らかに、その場合、無限に再帰的な型になってしまいます)。
の実装を通じてよりよく考えれば、それ自体を直接のメンバーとしてunordered_map
含めないようにすることができます。A
そのような実装はA
完全である必要はありません。ご指摘のとおり、Boost の実装はunordered_map
、この点でより適切に設計されています。