C++: static initializer_list transformation

140 views Asked by At

C++ standard defines that initializer_list will be transformed in the following manner:

struct X {
  X(std::initializer_list<double> v);
};
X x{ 1,2,3 };

The initialization will be implemented in a way roughly equivalent to this:

const double __a[3] = {double{1}, double{2}, double{3}};
X x(std::initializer_list<double>(__a, __a+3));

assuming that the implementation can construct an initializer_­list object with a pair of pointers.

Is it fair to assume that static const initializer_list will have the following type of transformation?

void foo() {
  static const std::initializer_list<int> kInitList{1, 2, 3};
  // other stuff.
}

Gets tranformed to:

void foo() {
  static const int __a[3] = {1, 2, 3};
  static const std::initializer_list<int> kInitList(__a, __a+3);
  // other stuff.
}

The backing array also becomes static (along with const).

1

There are 1 answers

0
Brian Bi On

The backing array for a std::initializer_list is described in [dcl.init.list]/5–6:

An object of type std​::​initializer_list<E> is constructed from an initializer list as if the implementation generated and materialized ([conv.rval]) a prvalue of type "array of N const E”, where N is the number of elements in the initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer list, and the std​::​initializer_list<E> object is constructed to refer to that array. [...]

The array has the same lifetime as any other temporary object ([class.temporary]), except that initializing an initializer_list object from the array extends the lifetime of the array exactly like binding a reference to a temporary. [...]

So when the initializer_list has static storage duration, it's not quite true that the array is declared with static storage duration too. It's a temporary object whose lifetime is extended to that of a reference with static storage duration.

Unresolved core issue CWG1634 asks whether temporary objects have storage duration and, if so, what that storage duration is. The intent seems to be that a temporary object whose lifetime is extended to that of some reference "inherits" that reference's storage duration. So perhaps eventually we will be able to say definitively that the array really does have static storage duration.

Nevertheless, the array is still a temporary object. That means, for example, that you can't use its address as a template argument the way you could if it were really defined as a static variable. [Link to rule]