我目前正在编写 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 文件格式的包装器).
我编写了使用 std::array 的代码,然后打算添加另一个用于检测和处理 std::array 类型的重载,但我不小心点击了编译,令我惊讶的是它起作用了!
我目前正在使用 MSVC 10,结果证明对于 std::array,如果 T 是 POD,则 std::array 是 POD.(这意味着我可以只使用重载 1 并且它可以工作.)
我的问题是,这是由 C++ 标准保证还是由实现决定.
我知道我可以自己检查标准,但我并不像我信任本网站上的一些语言律师那样信任自己,所以我认为最好获得第二意见".;)
谢谢
附言此处提供的代码(它是仅标头库):http://code.google.com/p/hadesmem/source/browse/trunk/HadesMem-v2/Hades-Memory/Hades-Memory/MemoryMgr.h#86
§23.3.1:
<块引用>数组是一个集合(8.5.1),可以用语法array a
其中 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).
Clause 9 的要求确实涵盖了array
,只要它的元素类型也是 POD 并且实现没有声明 operator=
或 move
> 里面 array
除了规范.
要真正肛门,17.5.2.2 说
<块引用>模板类数组
的伪代码注释是
//没有显式构造/复制/销毁聚合类型
construct/copy/destroy
是否包括 operator=
(赋值)或 move
?它可能应该,但我认为,根据最严格的解读,它确实如此.
请注意,这不仅会影响"POD 性,还会影响"约翰内斯提到的微不足道的可复制性.
I'm currently writing a C++ memory editing library and for the read/write APIs I use type traits (std::is_pod, std::is_same) and boost::enable_if to provide 3 overloads:
Overloads 2 and 3 are simply 'wrappers' around overload 1. (So if you're reading a std::vector or std::basic_string and T is not POD it will fail, as it should.)
Recently I wanted to use std::array for a bunch of reads and writes because I knew the size of the data I wanted to read and write at compile time (I was writing a wrapper around the PE file format).
I wrote the code to use std::array, and then intended to add another overload for detection and handling of std::array types, but I accidentally hit compile and to my surprise it worked!
I'm currently using MSVC 10 and it turns out that for std::array if T is POD then std::array is POD. (Which means I can just use overload 1 and it works.)
My question is whether this is guaranteed by the C++ standard or left up to the implementation.
I know I could check the standard myself, but I don't trust myself as much as I trust some of the language lawyers on this site, so I figured it would be best to get a 'second opinion'. ;)
Thanks
P.S. Code available here (it's a header-only lib): http://code.google.com/p/hadesmem/source/browse/trunk/HadesMem-v2/Hades-Memory/Hades-Memory/MemoryMgr.h#86
§23.3.1:
An array is an aggregate (8.5.1) that can be initialized with the syntax
array a<T, N> = { initializer-list };
where initializer-list is a comma separated list of up to N elements whose types are convertible to T.
In C++03, POD was defined in terms of aggregate: a class where every subobject is native or an aggregate is POD. So, by backwards compatibility, a C++0x std::array
is POD.
Or, to be anal, one can compare the bullet-points of §9/5 (defining trivial class) 9/6 (defining standard-layout) and 9/9 (combining preceding requirements into POD) with those of 8.5.1/1, which defines aggregates.
8.5.1:
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal- initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
Indeed the requirements in Clause 9 cover array
as long as its element type is also POD and the implementation does not declare operator=
or move
inside array
in addition to the specifications.
To be really anal, 17.5.2.2 says
- For the sake of exposition, Clauses 18 through 30 and Annex D do not describe copy/move constructors, assignment operators, or (non-virtual) destructors with the same apparent semantics as those that can be generated by default (12.1, 12.4, 12.8).
- It is unspecified whether the implementation provides explicit definitions for such member function signa- tures, or for virtual destructors that can be generated by default.
The note in the pseudo-code for template class array
is
// No explicit construct/copy/destroy for aggregate type
Does construct/copy/destroy
include operator=
(assignment) or move
? It probably should, but I don't think, by the strictest reading, it does.
Note that this "affects" not only POD-ness, but also trivial copyability as Johannes mentions.
这篇关于是 std::array<T, S>如果 T 是 POD 就保证是 POD?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!