15

The constexpr keyword was introduced in C++11, as (I think) was the corresponding idea of "constant expressions." However, this concept was implicitly present in C++98/c++03, since array declarations require a constant expression:

// valid:
int a[sizeof(int)];
int b[3+7];
int c[13/4];
const int n = 3;
int d[n];
// invalid:
int m = 4;
int e[m];

There are other "constant expressions", i.e., expressions that can be (and/or must be) evaluated at compile-time; one example is template arguments.

For pre-C++11, do the following exist, either in the C++98/03 standards or elsewhere?

  • A complete list of syntactic constructs requiring constant expressions (e.g. array declarations and template instantiations)
  • The rules governing such constant expressions (presumably this would just be a mapping from the items in the above list to their definitions in the standard)
Kyle Strand
  • 15,941
  • 8
  • 72
  • 167
  • Wait a minute!: "array declarations require a *constant* expression"? Why do you say that? – wallyk Sep 24 '14 at 20:14
  • 4
    @wallyk Because it’s true. – Konrad Rudolph Sep 24 '14 at 20:15
  • 1
    @KonradRudolph the gift of compiler extensions, it is amazing how many C++ developers do not know this. – Shafik Yaghmour Sep 24 '14 at 20:17
  • 2
    @wallyk Some compilers will allow a variable sized array on the stack, but will usually emit a warning. – More Axes Sep 24 '14 at 20:18
  • 1
    @MoreAxes usually it requires the proper flag to receive a warning, for `gcc` and `clang` that would be `-pedantic`. – Shafik Yaghmour Sep 24 '14 at 20:21
  • 1
    @ShafikYaghmour Indeed! As I was putting together those examples I was momentarily baffled when I found that I could compile `int e[m];` without warning or error (using `g++`). – Kyle Strand Sep 24 '14 at 20:37
  • @ShafikYaghmour I was taught to use all of those except `-Wconversion`, but I have a bad habit of not using them when I'm just trying to quickly check some C++ feature or other. – Kyle Strand Sep 24 '14 at 20:55
  • I edited my answer a bit, I think for the better, let me know if you feel like I left anything out. – Shafik Yaghmour Sep 27 '14 at 00:20
  • @ShafikYaghmour Thanks. Sorry, I've had a busy weekend and haven't had a chance to read it carefully yet, but I expect that when I do I'll accept it. – Kyle Strand Sep 29 '14 at 15:52

1 Answers1

13

constexpr and constant expressions are related in that constexpr tells us that a variable or function can be used where a constant expression can be used. This is what cppreference tell us:

The constexpr specifier declares that it is possible to evaluate the value of the function or variable at compile time. Such variables and functions can then be used where only compile time constant expressions are allowed.

Constant expresions were present before C++11 and the rules governing constant expressions pre C++11 are covered in the same place in the C++03 draft standard(this is the earliest public draft available closest to C++03)1 as the draft C++11 standard which is section 5.19 Constant expressions, cppreference has a good summary on this topic in Constant expressions page but it is geared toward C++11 and C++14 and it hard to tell what applies pre C++11.

The standard pre C++11 lists where a constant expression is required, in first paragraph of 5.19 and it looks complete:

In several places, C++ requires expressions that evaluate to an integral or enumeration constant: as array bounds (8.3.4, 5.3.4), as case expressions (6.4.2), as bit-field lengths (9.6), as enumerator initializers (7.2), as static member initializers (9.4.2), and as integral or enumeration non-type template arguments (14.3).

the rest of paragraph 1 says:

An integral constant-expression can involve only literals of arithmetic types (2.13, 3.9.1), enumerators, non-volatile const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumeration types can be used. In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, function-call, or comma operators shall not be used.

and is followed by 5 more paragraphs that list further requirements.

In C++11 there is a list of where constant expressions can be used in paragraph 3 but it does not clarify where they are required. You probably have to search for the term constant expression to find all the places where it is required and usually there will be a phrase similar to:

shall be a constant expression

The shall being the important term since violating a shall requirement makes the program ill-formed.

Alternatively you can use Annex A Grammar summary and search for constant-expression and that should cover all the places in the grammar where a constant expression is required, for example:

enumerator = constant-expression

Footnote:

  1. This answer to Where do I find the current C or C++ standard documents? has a complete list of the draft standards. Unfortunately the closest that is available to the public is from early 2005. The earlier versions require authentication. As far as I know section 5.19 did not change much.
Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • The draft standard you link to is from 2005...is that really for `C++03`? – Kyle Strand Sep 24 '14 at 20:01
  • @KyleStrand it is earliest public draft standard available, you can find a complete list of the draft available to all [here](http://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents). – Shafik Yaghmour Sep 24 '14 at 20:02