What is the rationale for requiring inclusion of <initializer_list>?
Asked Answered
B

1

28

From [dcl.init.list]

The template std​::​initializer_­list is not predefined; if the header <initializer_­list> is not included prior to a use of std​::​initializer_­list — even an implicit use in which the type is not named — the program is ill-formed.

Since std​::​initializer_­list is special-cased by the compiler anyway, why is it not treated as a first-class syntax of the language?

My thoughts on some possibilities and its counter-arguments:

Namespace pollution

Could be solved just like std::size_t, the inclusion of the header only introduces the identifier.

Note how auto sz = sizeof(0); is well-formed even without the inclusion of any headers, as opposed to auto il = {1, 2, 3}; being ill-formed.

Compilation overhead

libstdc++ implementation of std::initializer_list is literally less than 50 lines with no dependency on other headers. How big of overhead can that be?

Bookmobile answered 19/3, 2018 at 17:29 Comment(11)
Maybe it's to let old code avoid implicit list initialization where it would otherwise be ambiguous or undesired?Winer
Another example is typeid (needing std::type_info), as well as <=> in C++2a.Unfruitful
During <=>'s discussion, a maintainer of a popular implementation stated that it is infeasible for their compiler to synthesize the entire class type result of <=>. Synthesizing an entire class template would seem to be even more out of reach.Journalism
Modularity; and the C++ way. It is not a keyword, and not a real template.Missive
A bit of research into old minutes from a decade ago didn't reveal a reason, although it was stated in one of Bjarne's papers that braced initializer lists should be "opt-in" basically, what @Winer said.Newbill
@Winer As far as I'm aware, list initialization wasn't a breaking change. It wasn't legal to write std::vector<int> v{1, 2}; nor auto il = {1, 2}; before C++11. The only possibility of ambiguity is aggregates, but the semantics are preserved there.Bookmobile
You could equally consider std::cout as a "first-class" part of C++ since it's UB to add your own stuff to that namespace, so the only possible cout that could be in there is the iostream one. So why is using std::cout invalid if you don't include <iostream>? :-)Empress
@Empress std::cout has the semantics of a user defined object. std::initializer_list doesn't, the language rules have ridiculously many special cases to accommodate it.Bookmobile
Ftr, the relevant proposal is here, though I did not find a rationale for the wording.Alben
@Baum mit Augen♦: look at its date. It was proposed as an IMO desperate temporary solution; hoping that further language modifications allow an implementation or alternative, but it looks to have been forgotten later on.Caswell
The consistency with typeid and <=> has a counter-example: there's no #include <lambda> to use operator()(), operator+() or copy constructor of []{}Kosygin
C
1

It seems that there is no rational behind it. Maybe at the time there was an hope that further language resolutions and modifications allow an implementation, but this doesn't seems real now.

In any case further reading about the argument can be found here.

Chaplet answered 19/10, 2020 at 8:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.