std::initializer_list, braced initialization and header

The name of the pictureThe name of the pictureThe name of the pictureClash 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?










share|improve this question



















  • 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











  • 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














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?










share|improve this question



















  • 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











  • 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












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?










share|improve this question















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++






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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












  • 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











  • 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







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












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.






share|improve this answer






















  • 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










  • 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

















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






share|improve this answer




















  • 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

















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






share|improve this answer




















    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    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






























    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.






    share|improve this answer






















    • 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










    • 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














    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.






    share|improve this answer






















    • 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










    • 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












    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.






    share|improve this answer














    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.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    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 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
















    • 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










    • 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












    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






    share|improve this answer




















    • 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














    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






    share|improve this answer




















    • 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












    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






    share|improve this answer












    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







    share|improve this answer












    share|improve this answer



    share|improve this answer










    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
















    • 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










    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






    share|improve this answer
























      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






      share|improve this answer






















        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






        share|improve this answer












        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







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 19 mins ago









        P.W

        5,4111330




        5,4111330



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            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













































































            Comments

            Popular posts from this blog

            What does second last employer means? [closed]

            List of Gilmore Girls characters

            Confectionery