11

The specification of std::addressof was changed for C++17: it is now allowed to be a constant expression. However, cppreference says that:

The expression std::addressof(E) is a constant subexpression, if E is an lvalue constant subexpression.

  • What is a constant subexpression?
  • What is an example where std::addressof(E) will be a constant expression?
  • What is an example where std::addressof(E) will NOT be a constant expression?
Morwenn
  • 21,684
  • 12
  • 93
  • 152
Vincent
  • 57,703
  • 61
  • 205
  • 388

1 Answers1

11

This is explained here.

Introduce the following new definition to the existing list in 17.3 [definitions]: [Drafting note: If LWG 2234 is accepted before this issue, the accepted wording for the new definition should be used instead — end drafting note]

**constant subexpression** [defns.const.subexpr]

an expression whose evaluation as a subexpression of a *conditional-expression* *CE* (5.16 [expr.cond]) would not prevent *CE* from being a core constant expression (5.20 [expr.const]).

So "constant subexpression" roughly means "you can use it in a constant expression".

What is an example where std::addressof(E) will be a constant expression?

I believe it's intended to give a constant expression whenever &E does (assuming that & invokes the built-in address-of operator).

constexpr int x  = 42; // static storage duration
constexpr int* p1 = &x; // x is an lvalue constant subexpression
constexpr int* p2 = std::addressof(x); // x is an lvalue constant subexpression

What is an example where std::addressof(E) will NOT be a constant expression?

std::map<int, int> m;
void f() {
    int& r = m[42];
    constexpr int* z1 = &r; // error: r is not a constant subexpression
    constexpr int* z2 = std::addressof(r); // likewise

    constexpr int x = 43; // automatic storage duration
    constexpr const int y1 = *&x;                // ok; x is a constant subexpression
    constexpr const int y2 = *std::addressof(x); // likewise
    constexpr const int* p1 = &x;                // error: p1 points to an automatic object
    constexpr const int* p2 = std::addressof(x); // likewise

}
Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • so `x` is a constant expression, but not a constant subexpression, in the second example? Clear as mud – M.M Apr 12 '16 at 08:47
  • @M.M Actually `x` is also a constant expression in the second example... I probably should have picked a better example. – Brian Bi Apr 12 '16 at 17:23
  • I said not a constant *sub*expression – M.M Apr 12 '16 at 20:38
  • @M.M Oh, wait, let me start over. `x` is a constant expression if the lvalue-to-rvalue conversion is applied to it, but it cannot be a constant expression as a glvalue since it refers to an object of automatic storage duration. `x` is certainly a constant subexpression, though, whether as a glvalue or a prvalue. I should add a new example. – Brian Bi Apr 12 '16 at 20:42
  • @M.M I changed the example, hopefully it is more clear now. – Brian Bi Apr 12 '16 at 20:48
  • OK. In C++14, `x` (automatic) was a constant expression; so has the definition of *core constant expression* also been changed to demote some constant expressions to subexpressions? – M.M Apr 12 '16 at 21:02
  • @M.M not as far as I know... the wording is said to be relative to N3936, and N3936 has the same definition of "constant expression" as N4141, as far as I know. – Brian Bi Apr 12 '16 at 21:09
  • OK. I re-read the C++14 definition. I think the issue is that `x` (the second one) is a *core constant expression* (and a *converted constant expression*), but not a *constant expression*. So, back onto OP's first question: You've given the definition of *constant subexpression* but the implication is still unclear to me. Are all *core constant expression* also *constant subexpression*? Are there any *constant subexpression* which are not *core constant expression* ? – M.M Apr 12 '16 at 21:29