std::initializer_list, braced initialization and header
Clash Royale CLAN TAG#URR8PPP
up vote
8
down vote
favorite
While reading about a different topic I came across a weird behaviour, at least to me.
This whole thought originated from the special interactions between auto
and braces. If you write something like:
auto A = 1, 2, 3
the compiler will deduce A
to be a std::initializer_list
. The weird thing is that a similar rule applies not only to auto
, where there can be special reasons for it, but also to other things.
If you write the following:
template<typename T>
void f(std::vector<T> Vector)
// do something
you can't of course call it in this way:
f( 1, 2, 3);
even though a std::vector
can be braced initialized. However, if you substitute the std::vector
with std::initializer_list
, the call works and the compiler will properly deduce int
as the type T
. The more interesting thing is, however, that in the former case you need to #include <vector>
, in the latter you don't need to #include <initializer_list>
. This made me think and after a test I realized somehow std::initializer_list
don't need its own header, so it is in some way part of the "base" features.
Moreover, for everything to make sense, std::initializer_list
should be to standard objects in more or less the same way lambdas are to callable objects (in the strictest meaning, that is an object with a operator()
). In other words, unnamed braced definitions should default to std::initializer_list
just like lambdas are (mostly) unnamed callable objects.
Is this reasoning correct? Moreover, can this behaviour be changed and, if so, how?
UPDATE: the header for initializer_list
was found to be included transitively from iostream
(really weird). However, the question remains: why the call works for std::initializer_list
and not for std::vector
?
c++
add a comment |Â
up vote
8
down vote
favorite
While reading about a different topic I came across a weird behaviour, at least to me.
This whole thought originated from the special interactions between auto
and braces. If you write something like:
auto A = 1, 2, 3
the compiler will deduce A
to be a std::initializer_list
. The weird thing is that a similar rule applies not only to auto
, where there can be special reasons for it, but also to other things.
If you write the following:
template<typename T>
void f(std::vector<T> Vector)
// do something
you can't of course call it in this way:
f( 1, 2, 3);
even though a std::vector
can be braced initialized. However, if you substitute the std::vector
with std::initializer_list
, the call works and the compiler will properly deduce int
as the type T
. The more interesting thing is, however, that in the former case you need to #include <vector>
, in the latter you don't need to #include <initializer_list>
. This made me think and after a test I realized somehow std::initializer_list
don't need its own header, so it is in some way part of the "base" features.
Moreover, for everything to make sense, std::initializer_list
should be to standard objects in more or less the same way lambdas are to callable objects (in the strictest meaning, that is an object with a operator()
). In other words, unnamed braced definitions should default to std::initializer_list
just like lambdas are (mostly) unnamed callable objects.
Is this reasoning correct? Moreover, can this behaviour be changed and, if so, how?
UPDATE: the header for initializer_list
was found to be included transitively from iostream
(really weird). However, the question remains: why the call works for std::initializer_list
and not for std::vector
?
c++
1
A program that uses an initializer list but does not include<initializer_list>
header is ill-formed. For example, GCC complains: cannot deduce type of initializer list becausestd::initializer_list
was not found; include<initializer_list>
.
– Evg
34 mins ago
The issue with your function is that it's a template, and it deduces the template argumentT
as aninitializer_list
, whichvector
cannot hold. If you had simplyvoid f(std::vector<int> v)
then callingf(1,2,3);
works fine. I remember Scott Myers talked a bit aboutinitializer_list
and its idiosyncratic interaction betweenauto
and `vector but I'll have to see if I can dig it up
– Tas
32 mins ago
add a comment |Â
up vote
8
down vote
favorite
up vote
8
down vote
favorite
While reading about a different topic I came across a weird behaviour, at least to me.
This whole thought originated from the special interactions between auto
and braces. If you write something like:
auto A = 1, 2, 3
the compiler will deduce A
to be a std::initializer_list
. The weird thing is that a similar rule applies not only to auto
, where there can be special reasons for it, but also to other things.
If you write the following:
template<typename T>
void f(std::vector<T> Vector)
// do something
you can't of course call it in this way:
f( 1, 2, 3);
even though a std::vector
can be braced initialized. However, if you substitute the std::vector
with std::initializer_list
, the call works and the compiler will properly deduce int
as the type T
. The more interesting thing is, however, that in the former case you need to #include <vector>
, in the latter you don't need to #include <initializer_list>
. This made me think and after a test I realized somehow std::initializer_list
don't need its own header, so it is in some way part of the "base" features.
Moreover, for everything to make sense, std::initializer_list
should be to standard objects in more or less the same way lambdas are to callable objects (in the strictest meaning, that is an object with a operator()
). In other words, unnamed braced definitions should default to std::initializer_list
just like lambdas are (mostly) unnamed callable objects.
Is this reasoning correct? Moreover, can this behaviour be changed and, if so, how?
UPDATE: the header for initializer_list
was found to be included transitively from iostream
(really weird). However, the question remains: why the call works for std::initializer_list
and not for std::vector
?
c++
While reading about a different topic I came across a weird behaviour, at least to me.
This whole thought originated from the special interactions between auto
and braces. If you write something like:
auto A = 1, 2, 3
the compiler will deduce A
to be a std::initializer_list
. The weird thing is that a similar rule applies not only to auto
, where there can be special reasons for it, but also to other things.
If you write the following:
template<typename T>
void f(std::vector<T> Vector)
// do something
you can't of course call it in this way:
f( 1, 2, 3);
even though a std::vector
can be braced initialized. However, if you substitute the std::vector
with std::initializer_list
, the call works and the compiler will properly deduce int
as the type T
. The more interesting thing is, however, that in the former case you need to #include <vector>
, in the latter you don't need to #include <initializer_list>
. This made me think and after a test I realized somehow std::initializer_list
don't need its own header, so it is in some way part of the "base" features.
Moreover, for everything to make sense, std::initializer_list
should be to standard objects in more or less the same way lambdas are to callable objects (in the strictest meaning, that is an object with a operator()
). In other words, unnamed braced definitions should default to std::initializer_list
just like lambdas are (mostly) unnamed callable objects.
Is this reasoning correct? Moreover, can this behaviour be changed and, if so, how?
UPDATE: the header for initializer_list
was found to be included transitively from iostream
(really weird). However, the question remains: why the call works for std::initializer_list
and not for std::vector
?
c++
c++
edited 11 mins ago
asked 44 mins ago


Andrea Bocco
1628
1628
1
A program that uses an initializer list but does not include<initializer_list>
header is ill-formed. For example, GCC complains: cannot deduce type of initializer list becausestd::initializer_list
was not found; include<initializer_list>
.
– Evg
34 mins ago
The issue with your function is that it's a template, and it deduces the template argumentT
as aninitializer_list
, whichvector
cannot hold. If you had simplyvoid f(std::vector<int> v)
then callingf(1,2,3);
works fine. I remember Scott Myers talked a bit aboutinitializer_list
and its idiosyncratic interaction betweenauto
and `vector but I'll have to see if I can dig it up
– Tas
32 mins ago
add a comment |Â
1
A program that uses an initializer list but does not include<initializer_list>
header is ill-formed. For example, GCC complains: cannot deduce type of initializer list becausestd::initializer_list
was not found; include<initializer_list>
.
– Evg
34 mins ago
The issue with your function is that it's a template, and it deduces the template argumentT
as aninitializer_list
, whichvector
cannot hold. If you had simplyvoid f(std::vector<int> v)
then callingf(1,2,3);
works fine. I remember Scott Myers talked a bit aboutinitializer_list
and its idiosyncratic interaction betweenauto
and `vector but I'll have to see if I can dig it up
– Tas
32 mins ago
1
1
A program that uses an initializer list but does not include
<initializer_list>
header is ill-formed. For example, GCC complains: cannot deduce type of initializer list because std::initializer_list
was not found; include <initializer_list>
.– Evg
34 mins ago
A program that uses an initializer list but does not include
<initializer_list>
header is ill-formed. For example, GCC complains: cannot deduce type of initializer list because std::initializer_list
was not found; include <initializer_list>
.– Evg
34 mins ago
The issue with your function is that it's a template, and it deduces the template argument
T
as an initializer_list
, which vector
cannot hold. If you had simply void f(std::vector<int> v)
then calling f(1,2,3);
works fine. I remember Scott Myers talked a bit about initializer_list
and its idiosyncratic interaction between auto
and `vector but I'll have to see if I can dig it up– Tas
32 mins ago
The issue with your function is that it's a template, and it deduces the template argument
T
as an initializer_list
, which vector
cannot hold. If you had simply void f(std::vector<int> v)
then calling f(1,2,3);
works fine. I remember Scott Myers talked a bit about initializer_list
and its idiosyncratic interaction between auto
and `vector but I'll have to see if I can dig it up– Tas
32 mins ago
add a comment |Â
3 Answers
3
active
oldest
votes
up vote
5
down vote
This is not correct, you must include the <initializer_list>
header from [dcl.init.list]p2:
... 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 (9.1.7.4) — the program is ill-formed.
Mostly likely you are including the header transitively, perhaps from <vector>
We can see from a live godbolt examples that having no includes we obtain a diagnostic as required from gcc/clang/MSVC e.g.:
error: use of undeclared identifier 'std'
void foo( std::initializer_list<int>) {
^
and including either <vector>
or <iostream>
we no longer obtain a diagnsotic.
That's a possibility, but the only header I included are iostream and the built-in one for the project in VS, which should not inlcude anything else transitively.
– Andrea Bocco
26 mins ago
@AndreaBocco yup includingiostream
as well asvector
does it, see live godbolt ... if you comment out the includes you obtain a diagnostic
– Shafik Yaghmour
25 mins ago
Yes, you are right about the header being included transitively. Still, the other "half" of the question remain: why doesn't work to pass a braced initializer to the function for a vector while it does work for a initializer_list?
– Andrea Bocco
16 mins ago
add a comment |Â
up vote
0
down vote
Apparently std::initializer_list has an underlying array of type const T[N]. So no wonder it works!
Check out https://en.cppreference.com/w/cpp/utility/initializer_list
It doesn't.std::initializer_list
is just two pointers.
– Evg
28 mins ago
Moreover, I don't think it really matters. A vector also has an underlying array and still doesn't work. The point is the weirdness about initialization being possible without a proper header and the creation of a NAMED temporary object.
– Andrea Bocco
23 mins ago
add a comment |Â
up vote
0
down vote
GCC's implementation of vector
includes initializer_list
. This is probably true of other implementations as well. This is the reason you did not have to include initializer_list
separately.
Check out this source for GCC 4.6.2 which includes initializer_list
in the vector
header.
https://gcc.gnu.org/onlinedocs/gcc-4.6.2/libstdc++/api/a01069_source.html
add a comment |Â
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
5
down vote
This is not correct, you must include the <initializer_list>
header from [dcl.init.list]p2:
... 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 (9.1.7.4) — the program is ill-formed.
Mostly likely you are including the header transitively, perhaps from <vector>
We can see from a live godbolt examples that having no includes we obtain a diagnostic as required from gcc/clang/MSVC e.g.:
error: use of undeclared identifier 'std'
void foo( std::initializer_list<int>) {
^
and including either <vector>
or <iostream>
we no longer obtain a diagnsotic.
That's a possibility, but the only header I included are iostream and the built-in one for the project in VS, which should not inlcude anything else transitively.
– Andrea Bocco
26 mins ago
@AndreaBocco yup includingiostream
as well asvector
does it, see live godbolt ... if you comment out the includes you obtain a diagnostic
– Shafik Yaghmour
25 mins ago
Yes, you are right about the header being included transitively. Still, the other "half" of the question remain: why doesn't work to pass a braced initializer to the function for a vector while it does work for a initializer_list?
– Andrea Bocco
16 mins ago
add a comment |Â
up vote
5
down vote
This is not correct, you must include the <initializer_list>
header from [dcl.init.list]p2:
... 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 (9.1.7.4) — the program is ill-formed.
Mostly likely you are including the header transitively, perhaps from <vector>
We can see from a live godbolt examples that having no includes we obtain a diagnostic as required from gcc/clang/MSVC e.g.:
error: use of undeclared identifier 'std'
void foo( std::initializer_list<int>) {
^
and including either <vector>
or <iostream>
we no longer obtain a diagnsotic.
That's a possibility, but the only header I included are iostream and the built-in one for the project in VS, which should not inlcude anything else transitively.
– Andrea Bocco
26 mins ago
@AndreaBocco yup includingiostream
as well asvector
does it, see live godbolt ... if you comment out the includes you obtain a diagnostic
– Shafik Yaghmour
25 mins ago
Yes, you are right about the header being included transitively. Still, the other "half" of the question remain: why doesn't work to pass a braced initializer to the function for a vector while it does work for a initializer_list?
– Andrea Bocco
16 mins ago
add a comment |Â
up vote
5
down vote
up vote
5
down vote
This is not correct, you must include the <initializer_list>
header from [dcl.init.list]p2:
... 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 (9.1.7.4) — the program is ill-formed.
Mostly likely you are including the header transitively, perhaps from <vector>
We can see from a live godbolt examples that having no includes we obtain a diagnostic as required from gcc/clang/MSVC e.g.:
error: use of undeclared identifier 'std'
void foo( std::initializer_list<int>) {
^
and including either <vector>
or <iostream>
we no longer obtain a diagnsotic.
This is not correct, you must include the <initializer_list>
header from [dcl.init.list]p2:
... 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 (9.1.7.4) — the program is ill-formed.
Mostly likely you are including the header transitively, perhaps from <vector>
We can see from a live godbolt examples that having no includes we obtain a diagnostic as required from gcc/clang/MSVC e.g.:
error: use of undeclared identifier 'std'
void foo( std::initializer_list<int>) {
^
and including either <vector>
or <iostream>
we no longer obtain a diagnsotic.
edited 22 mins ago
answered 31 mins ago
Shafik Yaghmour
120k23302501
120k23302501
That's a possibility, but the only header I included are iostream and the built-in one for the project in VS, which should not inlcude anything else transitively.
– Andrea Bocco
26 mins ago
@AndreaBocco yup includingiostream
as well asvector
does it, see live godbolt ... if you comment out the includes you obtain a diagnostic
– Shafik Yaghmour
25 mins ago
Yes, you are right about the header being included transitively. Still, the other "half" of the question remain: why doesn't work to pass a braced initializer to the function for a vector while it does work for a initializer_list?
– Andrea Bocco
16 mins ago
add a comment |Â
That's a possibility, but the only header I included are iostream and the built-in one for the project in VS, which should not inlcude anything else transitively.
– Andrea Bocco
26 mins ago
@AndreaBocco yup includingiostream
as well asvector
does it, see live godbolt ... if you comment out the includes you obtain a diagnostic
– Shafik Yaghmour
25 mins ago
Yes, you are right about the header being included transitively. Still, the other "half" of the question remain: why doesn't work to pass a braced initializer to the function for a vector while it does work for a initializer_list?
– Andrea Bocco
16 mins ago
That's a possibility, but the only header I included are iostream and the built-in one for the project in VS, which should not inlcude anything else transitively.
– Andrea Bocco
26 mins ago
That's a possibility, but the only header I included are iostream and the built-in one for the project in VS, which should not inlcude anything else transitively.
– Andrea Bocco
26 mins ago
@AndreaBocco yup including
iostream
as well as vector
does it, see live godbolt ... if you comment out the includes you obtain a diagnostic– Shafik Yaghmour
25 mins ago
@AndreaBocco yup including
iostream
as well as vector
does it, see live godbolt ... if you comment out the includes you obtain a diagnostic– Shafik Yaghmour
25 mins ago
Yes, you are right about the header being included transitively. Still, the other "half" of the question remain: why doesn't work to pass a braced initializer to the function for a vector while it does work for a initializer_list?
– Andrea Bocco
16 mins ago
Yes, you are right about the header being included transitively. Still, the other "half" of the question remain: why doesn't work to pass a braced initializer to the function for a vector while it does work for a initializer_list?
– Andrea Bocco
16 mins ago
add a comment |Â
up vote
0
down vote
Apparently std::initializer_list has an underlying array of type const T[N]. So no wonder it works!
Check out https://en.cppreference.com/w/cpp/utility/initializer_list
It doesn't.std::initializer_list
is just two pointers.
– Evg
28 mins ago
Moreover, I don't think it really matters. A vector also has an underlying array and still doesn't work. The point is the weirdness about initialization being possible without a proper header and the creation of a NAMED temporary object.
– Andrea Bocco
23 mins ago
add a comment |Â
up vote
0
down vote
Apparently std::initializer_list has an underlying array of type const T[N]. So no wonder it works!
Check out https://en.cppreference.com/w/cpp/utility/initializer_list
It doesn't.std::initializer_list
is just two pointers.
– Evg
28 mins ago
Moreover, I don't think it really matters. A vector also has an underlying array and still doesn't work. The point is the weirdness about initialization being possible without a proper header and the creation of a NAMED temporary object.
– Andrea Bocco
23 mins ago
add a comment |Â
up vote
0
down vote
up vote
0
down vote
Apparently std::initializer_list has an underlying array of type const T[N]. So no wonder it works!
Check out https://en.cppreference.com/w/cpp/utility/initializer_list
Apparently std::initializer_list has an underlying array of type const T[N]. So no wonder it works!
Check out https://en.cppreference.com/w/cpp/utility/initializer_list
answered 30 mins ago


THEOS
314
314
It doesn't.std::initializer_list
is just two pointers.
– Evg
28 mins ago
Moreover, I don't think it really matters. A vector also has an underlying array and still doesn't work. The point is the weirdness about initialization being possible without a proper header and the creation of a NAMED temporary object.
– Andrea Bocco
23 mins ago
add a comment |Â
It doesn't.std::initializer_list
is just two pointers.
– Evg
28 mins ago
Moreover, I don't think it really matters. A vector also has an underlying array and still doesn't work. The point is the weirdness about initialization being possible without a proper header and the creation of a NAMED temporary object.
– Andrea Bocco
23 mins ago
It doesn't.
std::initializer_list
is just two pointers.– Evg
28 mins ago
It doesn't.
std::initializer_list
is just two pointers.– Evg
28 mins ago
Moreover, I don't think it really matters. A vector also has an underlying array and still doesn't work. The point is the weirdness about initialization being possible without a proper header and the creation of a NAMED temporary object.
– Andrea Bocco
23 mins ago
Moreover, I don't think it really matters. A vector also has an underlying array and still doesn't work. The point is the weirdness about initialization being possible without a proper header and the creation of a NAMED temporary object.
– Andrea Bocco
23 mins ago
add a comment |Â
up vote
0
down vote
GCC's implementation of vector
includes initializer_list
. This is probably true of other implementations as well. This is the reason you did not have to include initializer_list
separately.
Check out this source for GCC 4.6.2 which includes initializer_list
in the vector
header.
https://gcc.gnu.org/onlinedocs/gcc-4.6.2/libstdc++/api/a01069_source.html
add a comment |Â
up vote
0
down vote
GCC's implementation of vector
includes initializer_list
. This is probably true of other implementations as well. This is the reason you did not have to include initializer_list
separately.
Check out this source for GCC 4.6.2 which includes initializer_list
in the vector
header.
https://gcc.gnu.org/onlinedocs/gcc-4.6.2/libstdc++/api/a01069_source.html
add a comment |Â
up vote
0
down vote
up vote
0
down vote
GCC's implementation of vector
includes initializer_list
. This is probably true of other implementations as well. This is the reason you did not have to include initializer_list
separately.
Check out this source for GCC 4.6.2 which includes initializer_list
in the vector
header.
https://gcc.gnu.org/onlinedocs/gcc-4.6.2/libstdc++/api/a01069_source.html
GCC's implementation of vector
includes initializer_list
. This is probably true of other implementations as well. This is the reason you did not have to include initializer_list
separately.
Check out this source for GCC 4.6.2 which includes initializer_list
in the vector
header.
https://gcc.gnu.org/onlinedocs/gcc-4.6.2/libstdc++/api/a01069_source.html
answered 19 mins ago
P.W
5,4111330
5,4111330
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52924740%2fstdinitializer-list-braced-initialization-and-header%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
1
A program that uses an initializer list but does not include
<initializer_list>
header is ill-formed. For example, GCC complains: cannot deduce type of initializer list becausestd::initializer_list
was not found; include<initializer_list>
.– Evg
34 mins ago
The issue with your function is that it's a template, and it deduces the template argument
T
as aninitializer_list
, whichvector
cannot hold. If you had simplyvoid f(std::vector<int> v)
then callingf(1,2,3);
works fine. I remember Scott Myers talked a bit aboutinitializer_list
and its idiosyncratic interaction betweenauto
and `vector but I'll have to see if I can dig it up– Tas
32 mins ago