I've been experimenting with constexpr
. On my test compiler (g++ 4.6) this fails to compile with an error about out of bounds access. Is a compiler required to spot this at compile time?
#include <iostream>
constexpr const char *str = "hi";
constexpr int fail() {
return str[1000]; // Way past the end!
}
template <int N>
struct foo {
static void print() { std::cout << N << std::endl; }
};
int main() {
foo<fail()>::print();
}
§5.19/2 (on the second page; it really should be split into many paragraphs) forbids constant expressions containing
— an lvalue-to-rvalue conversion (4.1) unless it is applied to
— a glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding initialization, initialized with a constant expression, or
— a glvalue of literal type that refers to a non-volatile object defined with constexpr, or that refers to a sub-object of such an object
str[1000]
translates to * ( str + 1000 )
, which does not refer to a subobject of str
, in contrast with an in-bounds array access. So this is a diagnosable rule, and the compiler is required to complain.
EDIT: It seems there's some confusion about how this diagnosis comes about. The compiler checks an expression against §5.19 when it needs to be constant. If the expression doesn't satisfy the requirements, the compiler is required to complain. In effect, it is required to validate constant expressions against anything that might otherwise cause undefined behavior.* This may or may not involve attempting to evaluate the expression.
* In C++11, "a result that is not mathematically defined." In C++14, "an operation that would have undefined behavior," which by definition (§1.3.24) ignores behavior that the implementation might define as a fallback.
Yes, the compiler is supposed to catch this at compile time, if we look at section 5.19
Constant expressions paragraph 2 of the draft C++ standard it lists this as an exclusion for constant expressions:
— an operation that would have undefined behavior [ Note: including, for example, signed integer overflow (Clause 5), certain pointer arithmetic (5.7), division by zero (5.6), or certain shift operations (5.8) —end note ];
and issue 695 as far as I can tell says that undefined behavior is non-const and should issue a diagnostic:
The consensus of the CWG was that an expression like 1/0 should simply be considered non-constant; any diagnostic would result from the use of the expression in a context requiring a constant expression.
You can find more details at my self answered question here which also goes into the uses of this feature.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With