This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-12-19


615. Incorrect description of variables that can be initialized

Section: 9.4  [dcl.init]     Status: C++11     Submitter: comp.std.c++     Date: 30 January 2007

[Voted into WP at August, 2010 meeting.]

9.4 [dcl.init] paragraph 2 reads,

Automatic, register, static, and external variables of namespace scope can be initialized by arbitrary expressions involving literals and previously declared variables and functions.

Both “automatic” and “static” are used to describe storage durations, “register” is a storage class specifier which indicates the object has automatic storage duration, “external” describes linkage, and “namespace scope” is a kind of scope. Automatic, register, static and external, together with namespace scope, are used to restrict the “variables.”

Register objects are only a sub-set of automatic objects and thus the word “register” is redundant and should be elided. If register objects are to be emphasized, they should be mentioned like “Automatic (including register)...”

Variables having namespace scope can never be automatic; they can only be static, with either external or internal linkage. Therefore, there are in fact no “automatic variables of namespace scope,” and the “static” in “static variables of namespace scope” is useless.

In fact, automatic and static variables already compose all variables with either external linkage or not, and thus the “external” becomes redundant, too, and the quoted sentence seems to mean that all variables of namespace scope can be initialized by arbitrary expressions. But this is not true because not all internal variables of namespace scope can. Therefore, the restrictive “external” is really necessary, not redundant.

As a result, the erroneous restrictive “automatic, register, static” should be removed and the quoted sentence may be changed to:

External variables of namespace scope can be initialized by arbitrary expressions involving literals and previously declared variables and functions.

Notes from the April, 2007 meeting:

This sentence is poorly worded, but the analysis given in the issue description is incorrect. The intent is simply that the storage class of a variable places no restrictions on the kind of expression that can be used to initialize it (in contrast to C, where variables of static storage duration can only be initialized by constant expressions).

Proposed resolution (June, 2008):

Change 9.4 [dcl.init] paragraph 2 as follows:

Automatic, register, static, and external variables of namespace scope Variables of automatic, thread, and static storage duration can be initialized by arbitrary expressions involving literals and previously declared variables and functions...

Notes from the September, 2008 meeting:

The existing wording is intended to exclude block-scope extern declarations but to allow initializers in all other forms of variable declarations. The best way to phrase that is probably to say that all variable definitions (except for function parameters, where the initializer syntax is used for default arguments) can have arbitrary expressions as initializers, regardless of storage duration.

Proposed resolution (February, 2010):

Change 9.4 [dcl.init] paragraph 2 as follows:

Automatic, register, thread_local, static, and namespace-scoped external variables can be initialized by Except for objects declared with the constexpr specifier, for which see 9.2.6 [dcl.constexpr], an initializer in the definition of a variable can consist of arbitrary expressions involving literals and previously declared variables and functions, regardless of the variable's storage duration. [Example:...