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 wellformed? A second question is whether is would guaranteed to be
illformed, 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 usecase. 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 expressionstatements) would simplify the motivating
example implementation of operator[] to:
constexpr const T& operator[](unsigned i) const {
assert(i < N);
return data[i];
};
