我正在编写一个C ++内存编辑库,对于读/写API,我使用类型特征(std :: is_pod,std :: is_same)和boost :: enable_if来提供3个重载:
重载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
答案 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
内声明array
或template class array
规格。
真的肛门,17.5.2.2说
- 为了便于说明,第18至30条和附件D没有描述复制/移动构造函数,赋值运算符或(非虚拟)析构函数,它们具有与默认生成的语义相同的语义(12.1, 12.4,12.8)。
- 未指定实现是否为此类成员函数签名提供了显式定义,或者是否默认生成的虚拟析构函数。
醇>
// 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
的PODness没有任何保证,但 保证关于可复制性的琐碎,如下所示(如果我的结论中没有错误)。我们知道 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个特殊成员函数的聚合版本。 击>