Why isn’t `std::initializer_list` defined as a literal type?

The standard committee seems to intend on initializer_list being a literal type. However, it doesn’t look like it’s an explicit requirement, and seems to be a bug in the standard.

From § 3.9.10.5:

A type is a literal type if it is:
– a class type (Clause 9) that has all of the following properties:
– – it has a trivial destructor,
– – it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
– – all of its non-static data members and base classes are of non-volatile literal types.

From § 18.9.1:

namespace std {
  template<class E> class initializer_list {
  public:
    /* code removed */
    constexpr initializer_list() noexcept;
    // No destructor given, so trivial
    /* code removed */
  };
}

This satisfies the first and second requirements.

For the third requirement though:

From § 18.9.2 (emphasis mine):

An object of type initializer_list<E> provides access to an array of objects of type const E. [Note: A pair of pointers or a pointer plus a length would be obvious representations for initializer_list. initializer_list is used to implement initializer lists as specified in 8.5.4. Copying an initializer list does not copy the underlying elements.
—end note]

So there is no requirement for the private members of the implementation of initializer_list to be non-volatile literal types; however, because they mention that they believe a pair of pointers or a pointer and a length would be the “obvious representation,” they probably didn’t consider that someone might put something non-literal in the members of initializer_list.

I’d say that it’s both a bug in clang and the standard, probably.

Leave a Comment