The assert
-macro from <cassert>
provides a concise way of ensuring that a condition is met. If the argument evaluates to true
, it shall not have any further effects. However, can its invocation also be used inside a constant expression in that case?

- 60,038
- 8
- 155
- 203
-
currently active [gcc bug](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65985) – TemplateRex Jan 19 '16 at 19:23
1 Answers
This was dealt with by LWG 2234, which was brought back to attention after relaxed constraints on constexpr
functions had been introduced.
Proposed resolution:
This wording is relative to N3936.
Introduce the following new definition to the existing list in 17.3 [definitions]:
constant subexpression [defns.const.subexpr]
an expression whose evaluation as subexpression of a conditional-expression CE (5.16 [expr.cond]) would not prevent CE from being a core constant expression (5.20 [expr.const]).
Insert a new paragraph following 19.3 [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, orE contextually converted to
bool
(4 [conv]), is a constant subexpression that evaluates to the valuetrue
.
Constant subexpressions
This resolution introduced the notion of a constant subexpression - essentially an expression that is not (necessarily) a constant expression in itself, but can be used inside one. Consider for example
constexpr void f() {
int i = 0;
++i;
}
++i
is not a constant expression as it modifies an object whose lifetime started outside that expression (§5.20/(2.15)). However, the expression f()
is in its entirety a constant expression, because the previous point does not apply - i
's lifetime starts in f
. Hence ++i
is a constant subexpression, as ++i
does not prevent f()
from being a constant expression.
And assert
?
The second part of the resolution guarantees that assert(
E)
is a constant subexpression if either NDEBUG
is defined or the argument is itself a constant subexpression and evaluates to true
. This implies that a call to assert
can also be a bog-standard constant expression.
The following is well-formed:
constexpr int check(bool b) {
assert(b);
return 7;
}
constexpr int k = check(true);
b
is a constant subexpression and evaluates to true
in the call check(true)
, hence assert(b)
is a constant subexpression and therefore does not prevent check(true)
from being one.
Of course, the same pitfall as with static_assert
in templates is possible. Given that NDEBUG
isn't defined, this definition is ill-formed, no diagnostic required by §7.1.5/5 :
constexpr void fail() {
assert(false);
}

- 60,038
- 8
- 155
- 203
-
The terminology is a bit weird: a *constant subexpression CS* of a *constant expression CE* does not need to be a subexpression of CE, nor does it need to be a subexpression at all (a complete expression). – dyp May 25 '15 at 11:48
-
@dyp A subexpression of `e` can be `e` itself, can't it? (e.g. compare §1.9/10) Or are you actually referring to the CS not being part of CE at all? – Columbo May 25 '15 at 11:55
-
Not sure, is there a definition of *subexpression*? As far as I can tell, §1.9p10 defines *full-expression* rather than *subexpression* (though the wording "of another expression" might indicate that indeed subexpression is `<=` rather than `<`) -- that was point two I wanted to address. Point one is that the statements within the function are not subexpressions of the function call expression. -- oh, and happy Towel Day ;) – dyp May 25 '15 at 11:59
-
@dyp There is no definition, but I'd assume that what you mentioned is indeed the case. To point two: Yeah, I think I'll need to reword that. But what about /11: *"The evaluation of a full-expression can include the evaluation of subexpressions that are not **lexically part of the full-expression**."* This indicates that an expression can be a subexpression of `f()` without lexically appearing within it. – Columbo May 25 '15 at 12:02
-
I'm not sure that one can conclude that the expressions within the function `f` are subexpressions of `f()` from that paragraph: It talks about the *evaluation* of expressions, it doesn't say that those become/are part of `f()`. – dyp May 25 '15 at 12:14
-
@dyp Maybe we need to more subtly distinguish between lexical and evaluative subexpressions. I'll file an issue. – Columbo Jan 19 '16 at 16:10
-
@dyp It appears the term subexpression is used consistently as < and not <=, e.g.: "A subexpression `e1` of an expression `e` is an immediate subexpression if there is no subexpression `e2` of `e` such that `e1` is a subexpression of `e2`." can be found in [\[except.spec\]/12](http://eel.is/c++draft/except.spec#12). Mea culpa. – Columbo Feb 03 '16 at 20:18