30

As a question that came up during the discussion of this SO question:

Is it legal, maybe with N3471, to declare a constexpr std::initializer_list object? Example:

constexpr std::initializer_list<int> my_list{};

Why I think it may not be legal: initializer_list would have to be a literal type; but are there any guarantees that it is a literal type?

Citations from N3485.

[dcl.constexpr]/9:

A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized.

literal types requirements, [basic.types]/10, sub-bullet class types:

  • a class type (Clause 9) that has all of the following properties:
    • it has a trivial destructor,
    • every constructor call and full-expression in the brace-or-equal-initializers for non-static data members (if any) is a constant expression (5.19),
    • 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.

Bonus points ;) for answering if

constexpr std::initializer_list<int> my_list = {1,2,3,4,5};

is legal (with references). Though I think this is covered by the above + [dcl.init.list]/5

Community
  • 1
  • 1
dyp
  • 38,334
  • 13
  • 112
  • 177
  • Just to repeat what I said in the chat: I don't really get the point of making `std::initializer_list` functions `constexpr` (N3741) if we can't legally write the last example. – Morwenn Apr 17 '13 at 18:03
  • Another problem is the initialization. Common implementation uses pointers to access its underlying temporary array. If the array does not have static storage duration, initialization of the pointers [makes the whole initialization not a constant expression](http://www.eel.is/c++draft/expr.const#6.2). However, the storage duration of a temporary [seems not to be defined yet](https://stackoverflow.com/q/47945299/5376789). – xskxzr Mar 31 '18 at 09:08

1 Answers1

13

Update: The situation got a bit more complicated after the resolution of CWG DR 1684 removed the requirement quoted below. Some more information can be found in this discussion on the std-discussion mailing list and in the related question Why isn't `std::initializer_list` defined as a literal type?


[decl.constexpr]/8:

A constexpr specifier for a non-static member function that is not a constructor declares that member function to be const (9.3.1). [...] The class of which that function is a member shall be a literal type (3.9).

Therefore, the changes of N3471 guarantee std::initializer_list will be a literal type.


Note the constexpr ctor alone doesn't require std::initializer_list to be a literal type, see [dcl.constexpr]/4+8. Side note: An object of non-literal type with constexpr ctor can be initialized during constant initialization [basic.start.init]/2] (part of static initialization, performed before any dynamic initialization).

Community
  • 1
  • 1
dyp
  • 38,334
  • 13
  • 112
  • 177
  • I found this answer some hours after posting the question - wondering what use would be a `constexpr` ctor in a non-literal type. – dyp Apr 19 '13 at 11:06
  • 4
    I'm not sure to understand everything—is `constexpr std::initializer_list my_list = {1,2,3,4,5};` legal or not in C++14? – ChristopherC Dec 15 '14 at 09:17
  • @ChristopherC Sorry, it seems this requires a new investigation: The resolution of [CWG DR 1684](http://open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1684) removed the quoted passage from the C++14 Standard. I cannot find any other hints that `std::initializer_list` is required to be a literal type at the moment. – dyp Dec 15 '14 at 20:21
  • 1
    Thanks for the heads up!—these spec papers are still very cryptic to me. Using my C++14 + Clang 3.5 environment, I can see that all the methods from `std::initializer_list` are constexpr, so I thought the definition above had to be legal somehow, but it complains about the literal type thing so I wasn't sure if it was a compiler bug or something else. That being said, I agree with Morwenn—I don't see the point of all those constexpr if we can't even initialize the object... sounds like an half-baked class to me. Maybe I'll post a question to see if someone knows where it's heading to. – ChristopherC Dec 16 '14 at 00:58
  • @ChristopherC It is possible though that completely removing the part about "shall be a literal type" is an oversight. I just confirmed that clang++ trunk and g++ trunk both *still* require that the class is a literal type if it has non-static constexpr member functions. (So that's either a bug in both compilers, or something wrong with the Standard.) -- I have also no idea what constexpr member functions on non-literal types could be good for. – dyp Dec 16 '14 at 01:07
  • Thanks for checking this out! I've posted a question [here](http://stackoverflow.com/questions/27496004/why-isnt-stdinitializer-list-defined-as-a-literal-type), let's see. – ChristopherC Dec 16 '14 at 01:19