Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

c++11

stl

In order for a type to "play nicely" with the C++03 Standard Libraries, it was considered a bad idea to overload the operator&() since the address was need to correctly use the type and overloading it created unexpected problems; classic example here is ATL::CComBSTR.

  • With the advent of std::addressof() in C++11 and on, does this negate that old requirement(s) on the types being used in the standard library?
  • Is the requirement explicitly stated in (or removed from) the standard in C++11, i.e. is the standard library mandated by the specification to use std::addressof()?
like image 378
Niall Avatar asked Aug 27 '14 07:08

Niall


2 Answers

The value_type of a container only has a few requirements. They depend mainly on the container, but for the general case the requirements are at the very least MoveConstructible and MoveAssignable.

Looking at the C++11 standard tables for what these requirements mean, you get this:

§ 17.6.3.1 Table 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 Table 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                                     |
  |                                                               |
  +---------------------------------------------------------------+

There are more requirements given to a container depending on what it is, like DefaultConstructible. However, neither of the requirements require operator& to not be overloaded. They mainly deal with the constructibility of the value_type rather than the operator overloads provided by the type.

You can find the other tables over at § 17.6.3.1. The container requirements are specified over at § 23.

like image 146
Rapptz Avatar answered Oct 31 '22 00:10

Rapptz


The C++03 CopyConstructible requirements explicitly included the requirement that the address-of operator returned the actual address of the object, as noted in the comments § 20.1.3 (Table 30), hence types that overloaded that operator could run into problems with the Standard Library.

+------------+-------------+--------------------------+
| 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 simplifies the move (and copy constructible and assignable definitions) to a more basic syntax;

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

It makes no mention of the overloaded address of operator, but it also make little mention of std::addressof explicitly being required (outside some .resize() functions). std::allocator does however explicitly require the address of the types to be correct even in the presence of overloaded operator&().

In conclusion, there may be little in the specification to mandate the use of std::addressof() but in light of the simplified requirements and explicit object address requirements; the use of std::addressof() (or similar) is very close to being mandated.

My take-away here is; if you are writing generic code and require the address of an object, use std::addressof() and stick to being on the safe side.

like image 5
Niall Avatar answered Oct 30 '22 23:10

Niall