Title
assert() should allow usage in constant expressions
Status
c++17
Section
[assertions]
Submitter
Daniel Krügler

Created on 2013-01-12.00:00:00 last changed 81 months ago

Messages

Date: 2015-09-27.20:30:23

Proposed resolution:

This wording is relative to N3936.

Previous resolution [SUPERSEDED]:
  1. Introduce the following new definition to the existing list in [definitions]: [Drafting note: If LWG 2296 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 subexpression of a conditional-expression CE ([expr.cond]) would not prevent CE from being a core constant expression ([expr.const]).

  2. Insert a new paragraph following [assertions] p1 as indicated:

    -?- An expression assert(E) is a constant subexpression ([defns.const.subexpr]), if either

    • NDEBUG is defined at the point where assert(E) appears, or

    • E contextually converted to bool ([conv]), is a constant subexpression that evaluates to the value true.

  1. Introduce the following new definition to the existing list in [definitions]: [Drafting note: If LWG 2296 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 subexpression of a conditional-expression CE ([expr.cond]) would not prevent CE from being a core constant expression ([expr.const]).

  2. Insert a new paragraph following [assertions] p1 as indicated:

    -?- An expression assert(E) is a constant subexpression ([defns.const.subexpr]), if

    • NDEBUG is defined at the point where assert(E) appears, or

    • E contextually converted to bool ([conv]), is a constant subexpression that evaluates to the value true.

Date: 2017-02-02.00:41:18

[ Telecon 2015-06-30 ]

HH: standardizing existing practice
MC: what about the comment from Lenexa about striking "either"?
HH: all three implementations accept it
MC: update issue to strike "either" and move to Tentatively Ready

Date: 2015-05-22.19:38:14

[ Lenexa 2015-05-05 ]

MC : ran into this
Z : Is it guaranteed to be an expression?
MC : clarifies that assert runs at runtime, not sure what it does at compile time
STL : c standard guarantees its an expression and not a whole statement, so comma chaining it is ok
HH : Some implementations work as author wants it to
STL : also doing this as constexpr
DK/STL : discussing how this can actually work
HH : GCC 5 also implements it. We have implementor convergence
MC : Wants to do this without giving assert a special meaning
STL : NDEBUG being defined where assert appears is not how assert works. This is bug in wording. Should be "when assert is defined" or something like that. ... is a constant subexpression if NDEBUG is defined at the point where assert is last defined or redefined."
Would like to strike the "either" because ok if both debug or assertion is true. We want inclusive-or here
MC : is redefined needed?
STL : my mental model is its defined once and then redefined
HH : wants to up to P2
Z/STL : discussing how wording takes care of how/when assert is defined/redefefined
STL/WB : discussing whether to move to ready or review. -> Want to move it to ready.
ask for updated wording
p3 -> p2
plan to go to ready after checking wording

Date: 2014-06-15.00:00:00
Date: 2013-03-15.00:00:00

[ 2013-03-15 Issues Teleconference ]

Moved to Open.

We are still gaining experience with constexpr as a language feature, and there may be work in Evolution that would help address some of these concerns. Defer discussion until we have a group familiar with any evolutionary direction.

Date: 2014-06-08.18:08:32

It is unclear from the current specification whether assert() expressions can be used in (potential) constant expressions. As an example consider the implementation of a constexpr function:

#include <cassert>

template<class T, unsigned N>
struct array {
  T data[N];
  constexpr const T& operator[](unsigned i) const {
    return assert(i < N), data[i];
  }
};

int main() {
  constexpr array<int, 3> ai = {1, 2, 3};
  constexpr int i = ai[0];
  int j = ai[0];
  // constexpr int k = ai[5];
}

The first question is whether this program is guaranteed well-formed? A second question is whether is would guaranteed to be ill-formed, if we uncomment the last code line in main()?

The wording in [assertions] doesn't add anything significant to the C99 wording. From the C99 specification (7.2 p1 and 7.2.1.1 p2) we get already some valuable guarantees:

  • The expression assert(e) is a void expression for all expressions e independent of the definition of NDEBUG.

  • If NDEBUG is defined, assert(e) is equivalent to the expression void() (or anything that cannot be distinguished from that).

The current wording does not yet guarantee that assert expressions can be used in constant expressions, but all tested implementations (gcc, MSVC) would already support this use-case. It seems to me that this should be possible without giving assert a special meaning for the core language.

As a related comment it should be added, that there is a core language proposal that intents to relax some current constraints for constexpr functions and literal types. The most interesting one (making void a literal types and allowing for expression-statements) would simplify the motivating example implementation of operator[] to:

constexpr const T& operator[](unsigned i) const {
  assert(i < N);
  return data[i];
};
History
Date User Action Args
2017-07-30 20:15:43adminsetstatus: wp -> c++17
2015-10-27 16:52:45adminsetstatus: ready -> wp
2015-09-27 20:30:23adminsetmessages: + msg7545
2015-09-27 20:30:23adminsetstatus: open -> ready
2015-05-22 19:38:14adminsetmessages: + msg7440
2014-06-08 18:08:32adminsetmessages: + msg7015
2014-06-08 18:08:32adminsetmessages: + msg7014
2013-03-18 14:33:00adminsetmessages: + msg6442
2013-03-18 13:02:36adminsetstatus: new -> open
2013-01-12 00:00:00admincreate