std::addressof是否否定了STL运算符和要求?

Does std::addressof negate the STL operator& requirement?

本文关键字:运算符 STL addressof 是否 std      更新时间:2023-10-16

为了让一个类型在C++03标准库中"玩得很好",重载operator&()被认为是个坏主意,因为地址需要正确使用该类型,而重载会产生意想不到的问题;这里的经典例子是CCD_ 2。

  • 随着std::addressof()在C++11中的出现,这是否否定了对标准库中使用的类型的旧要求
  • 该要求是否在C++11中的标准中明确说明(或从中删除),即规范是否要求标准库使用std::addressof()

容器的value_type只有几个要求。它们主要取决于容器,但对于一般情况,要求至少是MoveConstructibleMoveAssignable

查看C++11标准表了解这些要求的含义,您会得到以下信息:

§17.6.3.1表20(MoveConstructible):

 +----------------------------------------------------------+
 | Expression         |       Post Condition                |
 |----------------------------------------------------------+
 | T u = rv;          | u is equivalent to the              |
 |                    | value of rv before the construction |
 +----------------------------------------------------------+
 | T u(rv);           | T(rv) is equivalent to the          |
 |                    | value of rv before the construction |
 +----------------------------------------------------------+
 | rv's state is unspecified.                               |
 |                                                          |
 +----------------------------------------------------------+

§17.6.3.1表22(MoveAssignable)。

  +-----------+--------------+-------------+----------------------+
  | Expression|  Return Type | Return value| Post Condition       |
  |-----------|--------------|-------------|----------------------|
  | t = rv;   |  T&          | t           | t is equivalent to   |
  |           |              |             | the value of rv      |
  |           |              |             | before the assignment|
  |           |              |             |                      |
  +---------------------------------------------------------------+
  | rv's state is unspecified                                     |
  |                                                               |
  +---------------------------------------------------------------+

容器有更多的要求,这取决于它是什么,比如DefaultConstructible。但是,这两个要求都不要求operator&过载。它们主要处理value_type的可构造性,而不是类型提供的运算符重载。

您可以在§17.6.3.1中找到其他表格。§23中规定了集装箱要求。

C++03 CopyConstructible要求明确包括运算符地址返回对象实际地址的要求,如注释§20.1.3(表30)所述,因此重载该运算符的类型可能会遇到标准库问题。

+------------+-------------+--------------------------+
| expression | return type | requirement              |
+------------+-------------+--------------------------+
| T(t)       |             | t is equivalent to T(t)  |
+------------+-------------+--------------------------+
| T(u)       |             | u is equivalent to T(u)  |
+------------+-------------+--------------------------+
| t.~T()     |             |                          |
+------------+-------------+--------------------------+
| &t         | T*          | denotes the address of t |
+------------+-------------+--------------------------+
| &u         | const T*    | denotes the address of u |
+------------+-------------+--------------------------+

C++11简化了移动(以及复制可构造和可分配的定义)到更基本的语法;

T ( rvalue ); // move construct
T u = rvalue; // move assign
T ( value ); // copy construct
T u = value; // copy assign

它没有提及运算符的重载地址,但也很少提及明确需要std::addressof(在某些.resize()函数之外)。然而,即使在存在过载的CCD_ 16的情况下,CCD_ 15也明确要求类型的地址是正确的。

总之,规范中可能很少强制使用std::addressof(),但考虑到简化的要求和明确的对象地址要求;CCD_ 18(或类似物)的使用非常接近于被强制使用。

我的收获是;如果您正在编写泛型代码,并且需要对象的地址,请使用std::addressof()并坚持安全起见。