【问题标题】:typedef and incomplete typetypedef 和不完整类型
【发布时间】:2010-06-19 08:15:12
【问题描述】:

最近,当我更改代码中的某些容器、分配器时,我遇到了很多关于 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&lt;foo&gt;::pointer foo_ptr 被 typedef stack_alloc&lt;foo,10&gt;::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_typepointerreferenceiterator等不依赖于T的完整性,并且知道没有完整类型就无法实例化类,那么这样的typedef如何以独立于特定容器或分配器的通用方式制作?

注意:

  • 为了完整起见,在“真实”代码中,我使用带有 vector 的小型本地内存,而不是用 std::array 替换它,尽管问题仍然存在。
  • stack_alloc 代码远未完成,仅显示部分问题。
  • 我知道数组、sizeof 等需要完整的可用类型。但我没有创建 all_foos 类型的对象,但 foo 不完整。
  • 我的断言是指针、引用等不应依赖于类型的完整性。否则无法定义像struct foo{ foo_ptr p;}; 这样的构造。虽然可能foo_ref 不能是foo&amp; 以外的任何东西,但foo_ptr 可以。令人惊讶的是,GCC 实现没有 tr1::array 的嵌套指针类型。
  • 主要知道什么不能做,并且有兴趣知道在这种情况下可以做什么。所以期待一个好的设计作为解决方案。

【问题讨论】:

    标签: c++ typedef


    【解决方案1】:

    类型必须完整才能在标准容器中使用,否则行为未定义(§17​.4.3.6/2)。所以唯一的标准解决方案是在定义类之前不要创建typedef

    我不明白中间容器的用途:

    struct foo;//incomplete type.
    typedef foo& foo_ref;
    

    无论如何,您只需要首先定义完整的类型,真的。要在一个类中定义typedef,该类必须被实例化,这意味着整个事物必须能够根据需要使用T

    例如,stack_alloc 必须有 T 是一个完整的类型(sizeof(T) 才能工作),否则无法实例化该类。如果无法实例化该类,则无法从中获取typedef。因此,如果 T 不完整,您将永远从中获取 typedef

    【讨论】:

    • 容器是存储 foo 的地方。结构 foo; typedef std::vector > all_foos; typedef all_foos::pointer foo_ptr;结构栏 { foo_ptr p;}; struct foo { std::vector 条形; }; all_foos the_instance;这有意义吗?如果我定义 struct bar { foo* p; };它可能不起作用,因为 alloc 的指针可能与 foo*.typedef foo& foo_ref; 不同。没关系,因为没有其他方式可以定义参考。
    • @abir:我真的想不出指针类型会改变的例子。在任何情况下,如果你真的想得到那些 typedef,你只需要包含foo 的完整定义。没有别的办法。
    【解决方案2】:

    Compiller 不知道不完整类型的大小,因此它不能实例化它,也不能为其分配一些内存。拥有指向对象的指针(如 typedef std::tr1::array&lt;foo*, 5&gt; all_foos; )而不是对象本身的实例可以解决此问题。

    【讨论】:

      猜你喜欢
      • 2012-11-18
      • 1970-01-01
      • 1970-01-01
      • 2011-09-10
      • 1970-01-01
      • 2016-05-05
      • 2017-02-25
      • 2011-07-13
      • 2021-09-01
      相关资源
      最近更新 更多