最近,当我在代码中更改了某些容器,分配器时,我遇到了很多typedef和不完整类型的问题。
我之前有过什么
struct foo;//incomplete type.
typedef std::vector<foo> all_foos;
typedef all_foos::reference foo_ref;
虽然不完全不确定上述行是否合法,但这适用于我使用的每个实现。当我认为我可以使用std::tr1::array
完成工作时,用
typedef std::tr1::array<foo,5> all_foos;
typedef all_foos::reference foo_ref;
这里所有内容都会中断,因为编译器尝试实例化array
并失败,因为foo
是不完整类型。我所需要的是对foo
的引用,对数组的“其他部分”不太感兴趣。当我创建这样的数组时,foo肯定会完全可用。
当typedef std::allocator<foo>::pointer foo_ptr
被typedef stack_alloc<foo,10>::pointer foo_ptr
取代时,同样的问题。其中stack_alloc
实现就像
template<typename T,unsigned N>
struct stack_alloc
{
typedef T* pointer;
typedef std::tr1::aligned_storage<sizeof(T)*N, std::tr1::alignment_of<T>::value> buffer;
};
假设value_type
,pointer
,reference
,iterator
等不依赖T
的完整性,并且知道班级不能实例化没有完整类型,如何以通用方式独立于特定容器或分配器来制作这样的typedef?
注意:
vector
的小本地内存,而不是将其替换为std::array
,但问题仍然存在。stack_alloc
代码远未完成,只显示问题的一部分。all_foos
类型的对象,其中foo
不完整。struct foo{ foo_ptr p;};
的构造。虽然foo_ref
可能不是foo&
,但foo_ptr
可能不是tr1::array
。令人惊讶的是,GCC实现没有{{1}}的嵌套指针类型。答案 0 :(得分:7)
必须完成一个类型才能在标准容器中使用,或者行为未定义(§17.4.3.6/ 2)。因此,唯一的标准解决方案是在定义类之前不要使用typedef
。
我没有得到中间容器的用途:
struct foo;//incomplete type.
typedef foo& foo_ref;
在任何情况下,你都必须首先定义完整的类型。要在类中定义typedef
,必须实例化该类,这意味着整个事物必须能够根据需要使用T
例如,stack_alloc
必须T
为完整类型(sizeof(T)
才能生效),否则无法实例化该类。如果无法实例化该类,则无法从中获取typedef
。如果typedef
不完整,你永远不会从中获取T
。
答案 1 :(得分:2)
Compiller不知道不完整类型的大小,因此它不能实例化它也不能为它分配一些内存。拥有指向对象的指针(如typedef std::tr1::array<foo*, 5> all_foos;
)而不是对象本身的实例可以解决这个问题。