Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

This is a follow-up of this question: Is it legal to declare a constexpr initializer_list object?.

Since C++14, the std::initializer_list class has all of its methods marked with constexpr. It seems natural to be able to initialize an instance by doing constexpr std::initializer_list<int> list = {1, 2, 3}; but Clang 3.5 complains about list not being initialized by a constant expression. As dyp pointed out in a comment, any requirement for std::initializer_list to be a literal type seem to have vanished from the specs.

What's the point of having a class fully defined as constexpr if we can't even initialize it as such? Is it an oversight in the standard and will get fixed in the future?

like image 547
ChristopherC Avatar asked Dec 16 '14 01:12

ChristopherC


1 Answers

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.

like image 113
OmnipotentEntity Avatar answered Sep 22 '22 20:09

OmnipotentEntity