如果T是POD,std :: array <t,s =“”>是否保证为POD?</t,>

时间:2010-09-09 06:21:48

标签: c++ templates stl tr1 c++11

我正在编写一个C ++内存编辑库,对于读/写API,我使用类型特征(std :: is_pod,std :: is_same)和boost :: enable_if来提供3个重载:

  1. POD类型。例如MyMem.Read(SomeAddress);
  2. 字符串类型。例如MyMem.Read&GT;(SomeAddress); (这实际上并没有读出C ++字符串,它会读出一个C风格的字符串并将其转换为C ++字符串。)
  3. 矢量类型。例如MyMem.Read&gt;(SomeAddress,NumElem); (这实际上并没有读出一个向量,而是读出一个C风格的数组并将其转换为向量。)
  4. 重载2和3只是在重载1周围的'包装器'。(所以如果你正在读取std :: vector或std :: basic_string而T不是POD它会失败,因为它应该。)

    最近我想使用std :: array进行一堆读写操作,因为我知道我想在编译时读写的数据的大小(我正在编写一个围绕PE文件格式的包装器)。 / p>

    我编写了使用std :: array的代码,然后打算为std :: array类型的检测和处理添加另一个重载,但是我不小心遇到了编译,我惊讶它工作了!

    我目前正在使用MSVC 10,事实证明,对于std :: array,如果T是POD,则std :: array是POD。 (这意味着我可以使用重载1并且它可以工作。)

    我的问题是这是由C ++标准保证还是由实现完成。

    我知道我可以自己检查标准,但我不相信自己,因为我相信这个网站上的一些语言律师,所以我认为最好得到'第二意见'。 ;)

    由于

    P.S。这里提供的代码(它是一个只有头文件的lib): http://code.google.com/p/hadesmem/source/browse/trunk/HadesMem-v2/Hades-Memory/Hades-Memory/MemoryMgr.h#86

3 个答案:

答案 0 :(得分:11)

§23.3.1:

  

数组是一个聚合(8.5.1),可以使用语法array a<T, N> = { initializer-list };进行初始化   其中initializer-list是一个逗号分隔的列表,最多包含N个元素,其类型可转换为T.

在C ++ 03中,POD是根据聚合定义的:一个类,其中每个子对象都是本机的,或者聚合是POD。因此,通过向后兼容性,C ++ 0x std::array是POD。

或者,作为肛门,人们可以将§9/ 5(定义普通类)9/6(定义标准布局)和9/9(将先前要求组合到POD中)与8.5的要点进行比较。 .1 / 1,定义聚合。

8.5.1:

  

聚合是一个数组或类(第9节),没有用户提供的构造函数(12.1),没有用于非静态数据成员(9.2)的大括号或相等初始值,没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚函数(10.3)。

第9条中的要求涵盖array,只要其元素类型也是POD,并且除了operator=之外,实现不会在move内声明arraytemplate class array规格。

真的肛门,17.5.2.2说

  
      
  1. 为了便于说明,第18至30条和附件D没有描述复制/移动构造函数,赋值运算符或(非虚拟)析构函数,它们具有与默认生成的语义相同的语义(12.1, 12.4,12.8)。
  2.   
  3. 未指定实现是否为此类成员函数签名提供了显式定义,或者是否默认生成的虚拟析构函数。
  4.   

// No explicit construct/copy/destroy for aggregate type的伪代码中的注释是

  

construct/copy/destroy

operator=是否包含move(作业)或{{1}}?它可能应该,但我不认为,通过最严格的阅读,确实如此。

请注意,这不仅会“影响”POD,而且会影响Johannes提到的琐碎可复制性。

答案 1 :(得分:7)

根据POD的定义:

  

9个课程

     

9 POD结构是一个既是普通类又是标准布局类的类,并且没有非静态非POD结构类型的非数据成员,非POD联合(或此类型的数组)。类似地,POD联合是一个简单类和标准布局类的联合,并且没有非POD结构类型的非静态数据成员,非POD联合(或这种类型的数组)。 POD类是POD结构或POD联合的类。

[强调我的]

std::array确实满足了作为一个简单的标准布局类模板的所有要求。所以你的问题的答案是肯定的。

答案 2 :(得分:1)

Potatoswatter在我的结论中发现错误。 C ++明确允许实现明确定义赋值运算符“具有相同的表观语义”。这将使它成为一种非平凡的可复制类型。制作社区维基...


<击> 在我看来,你不想针对PODnes进行测试,而是针对平易可复制的进行测试,这样做的限制较少。因为这就是可以与memcpy和朋友一起使用的C ++ 0x约束类型。

<击>

虽然我认为对std::array 的PODn​​ess没有任何保证,但 保证关于可复制性的琐碎,如下所示(如果我的结论中没有错误)。我们知道std::array是一个聚合,聚合是

  

聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有大括号或等于   非静态数据成员的初始化程序(9.2),没有私有或受保护的非静态数据成员(第11条),   没有基类(第10条),也没有虚函数(10.3)。

虽然为类具有

的类定义了可复制性
  
      
  • 没有非平凡的副本构造函数(12.8),
  •   
  • 没有非平凡的移动构造函数(12.8),
  •   
  • 没有非平凡的复制赋值运算符(13.5.3,12.8),
  •   
  • 没有非平凡的移动赋值运算符(13.5.3,12.8)和
  •   
  • 有一个简单的析构函数(12.4)。
  •   

std::array没有析构函数(作为std::array定义中的注释)。尽管std::array的类定义中的注释声称,但这似乎并未遵循聚合类的定义。

剩余的4个要求来自缺少基础,虚函数和用户提供的4个特殊成员函数的聚合版本。