Strange behavior of std::initializer_list of std::stringsTwo string literals have the same pointer value?How...

Is it possible for a person to be tricked into becoming a lich?

Which is the correct version of Mussorgsky's Pictures at an Exhibition?

Why does Sauron not permit his followers to use his name?

What checks exist against overuse of presidential pardons in the USA?

Can two aircraft be allowed to stay on the same runway at the same time?

Terminology of atomic spectroscopy: Difference Among Term, States and Level

Understanding data transmission rates over copper wire

Why did I get UK entry stamps in my British passport?

Create a list of snaking numbers under 50,000

Turning an Abelian Group into a Vector Space

Why does the U.S. military maintain their own weather satellites?

Fixing a blind bolt hole when the first 2-3 threads are ruined?

Small RAM 4 KB on the early Apple II?

Did the Apollo Guidance Computer really use 60% of the world's ICs in 1963?

Find the logic in first 2 statements to give the answer for the third statement

What's the origin of the concept of alternate dimensions/realities?

Is this homebrew "Faerie Fire Grenade" unbalanced?

What caused the end of cybernetic implants?

What is the following VRP?

Printing a list as "a, b, c." using Python

Moscow SVO airport, how to avoid scam taxis without pre-booking?

How to differentiate between two people with the same name in a story?

What am I looking at here at Google Sky?

'spazieren' - walking in a silly and affected manner?



Strange behavior of std::initializer_list of std::strings


Two string literals have the same pointer value?How to concatenate a std::string and an int?What's the best way to trim std::string?How do I iterate over the words of a string?How to convert std::string to lower case?How to convert a std::string to const char* or char*?std::wstring VS std::stringWhy is “using namespace std;” considered bad practice?Undefined behavior and sequence pointsEasiest way to convert int to string in C++How can I get sizeof a vector::value_type?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}







6















This question is already asked most likely, but I did not find the answer.



The code below compiles with gcc but crashes at runtime, with std::length_error (live).



void test(const std::string &value) { std::cout << "string overload: " << value << std::endl; }

//void test(const std::vector<std::string> &) { std::cout << "vector overload" << std::endl; }

int main()
{
test({"one", "two"});
}


The ability to create a string from the initializer list of strings seems controversial and, for example, does not make it possible to create the overload commented out in the code above.



But even if such construction is allowed, why does it lead to a failure?










share|improve this question



























  • initializer_list version of std::string is applicable only to list of chars, not list of strings. With list of strings you get standard list initialization of object. Commented overload is ok, when not ambiguous. I.e. if list has more than 2 elements.

    – sklott
    13 hours ago













  • Note (since this isn't the main question): The problem here comes from "one" and "two" not being std::strings. You can do either test({{"one"}, {"two"}}); or use C++17 string literals test({"one"s, "two"s}); (with using namespace std::literals;). Either one will work.

    – Max Langhof
    13 hours ago













  • @Max Langhof, thanks!

    – Yuriy
    12 hours ago


















6















This question is already asked most likely, but I did not find the answer.



The code below compiles with gcc but crashes at runtime, with std::length_error (live).



void test(const std::string &value) { std::cout << "string overload: " << value << std::endl; }

//void test(const std::vector<std::string> &) { std::cout << "vector overload" << std::endl; }

int main()
{
test({"one", "two"});
}


The ability to create a string from the initializer list of strings seems controversial and, for example, does not make it possible to create the overload commented out in the code above.



But even if such construction is allowed, why does it lead to a failure?










share|improve this question



























  • initializer_list version of std::string is applicable only to list of chars, not list of strings. With list of strings you get standard list initialization of object. Commented overload is ok, when not ambiguous. I.e. if list has more than 2 elements.

    – sklott
    13 hours ago













  • Note (since this isn't the main question): The problem here comes from "one" and "two" not being std::strings. You can do either test({{"one"}, {"two"}}); or use C++17 string literals test({"one"s, "two"s}); (with using namespace std::literals;). Either one will work.

    – Max Langhof
    13 hours ago













  • @Max Langhof, thanks!

    – Yuriy
    12 hours ago














6












6








6








This question is already asked most likely, but I did not find the answer.



The code below compiles with gcc but crashes at runtime, with std::length_error (live).



void test(const std::string &value) { std::cout << "string overload: " << value << std::endl; }

//void test(const std::vector<std::string> &) { std::cout << "vector overload" << std::endl; }

int main()
{
test({"one", "two"});
}


The ability to create a string from the initializer list of strings seems controversial and, for example, does not make it possible to create the overload commented out in the code above.



But even if such construction is allowed, why does it lead to a failure?










share|improve this question
















This question is already asked most likely, but I did not find the answer.



The code below compiles with gcc but crashes at runtime, with std::length_error (live).



void test(const std::string &value) { std::cout << "string overload: " << value << std::endl; }

//void test(const std::vector<std::string> &) { std::cout << "vector overload" << std::endl; }

int main()
{
test({"one", "two"});
}


The ability to create a string from the initializer list of strings seems controversial and, for example, does not make it possible to create the overload commented out in the code above.



But even if such construction is allowed, why does it lead to a failure?







c++ constructor initializer-list overload-resolution constructor-overloading






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 12 hours ago









Vlad from Moscow

152k14 gold badges92 silver badges195 bronze badges




152k14 gold badges92 silver badges195 bronze badges










asked 13 hours ago









YuriyYuriy

3411 silver badge12 bronze badges




3411 silver badge12 bronze badges
















  • initializer_list version of std::string is applicable only to list of chars, not list of strings. With list of strings you get standard list initialization of object. Commented overload is ok, when not ambiguous. I.e. if list has more than 2 elements.

    – sklott
    13 hours ago













  • Note (since this isn't the main question): The problem here comes from "one" and "two" not being std::strings. You can do either test({{"one"}, {"two"}}); or use C++17 string literals test({"one"s, "two"s}); (with using namespace std::literals;). Either one will work.

    – Max Langhof
    13 hours ago













  • @Max Langhof, thanks!

    – Yuriy
    12 hours ago



















  • initializer_list version of std::string is applicable only to list of chars, not list of strings. With list of strings you get standard list initialization of object. Commented overload is ok, when not ambiguous. I.e. if list has more than 2 elements.

    – sklott
    13 hours ago













  • Note (since this isn't the main question): The problem here comes from "one" and "two" not being std::strings. You can do either test({{"one"}, {"two"}}); or use C++17 string literals test({"one"s, "two"s}); (with using namespace std::literals;). Either one will work.

    – Max Langhof
    13 hours ago













  • @Max Langhof, thanks!

    – Yuriy
    12 hours ago

















initializer_list version of std::string is applicable only to list of chars, not list of strings. With list of strings you get standard list initialization of object. Commented overload is ok, when not ambiguous. I.e. if list has more than 2 elements.

– sklott
13 hours ago







initializer_list version of std::string is applicable only to list of chars, not list of strings. With list of strings you get standard list initialization of object. Commented overload is ok, when not ambiguous. I.e. if list has more than 2 elements.

– sklott
13 hours ago















Note (since this isn't the main question): The problem here comes from "one" and "two" not being std::strings. You can do either test({{"one"}, {"two"}}); or use C++17 string literals test({"one"s, "two"s}); (with using namespace std::literals;). Either one will work.

– Max Langhof
13 hours ago







Note (since this isn't the main question): The problem here comes from "one" and "two" not being std::strings. You can do either test({{"one"}, {"two"}}); or use C++17 string literals test({"one"s, "two"s}); (with using namespace std::literals;). Either one will work.

– Max Langhof
13 hours ago















@Max Langhof, thanks!

– Yuriy
12 hours ago





@Max Langhof, thanks!

– Yuriy
12 hours ago












2 Answers
2






active

oldest

votes


















11















It calls



string(const char* b, const char* e) 


string ctor overload.



It works only if b and e points to the same string literal. Otherwise it is undefined behaviour.






share|improve this answer


























  • Yes, Thanks. Is there any idea how to achieve the choice of overloading with a vector, preferably without changing the syntax of the call?

    – Yuriy
    13 hours ago






  • 1





    I cannot find this overload in cppreference. What is it doing?

    – Yksisarvinen
    13 hours ago











  • Came to the same conclusion in a somehow funny way: Live Demo on coliru. Ok, ok, a debugger would've been even simpler - but I got a nice demonstration. ;-)

    – Scheff
    13 hours ago






  • 3





    @Yksisarvinen template< class InputIt > basic_string( InputIt first, InputIt last, const Allocator& alloc = Allocator() );

    – rafix07
    13 hours ago











  • @Yuriy What do you mean by "the choice of overloading with a vector"? What are you trying to do?

    – Lightness Races in Orbit
    13 hours ago



















6















For starters there is no used the constructor that accepts an initializer list because such a constructor looks like



basic_string(initializer_list<charT>, const Allocator& = Allocator());
^^^^^


So the compiler searches another appropriate constructor and it finds such a constructor. It is the constructor



template<class InputIterator>
basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator());


That is the expressions "one" and "two" are considered as iterators of the type const char *.



So the function test has undefined behavior.



You could write for example (provided that string literals with the same content are stored as one string literal in memory, which is not guaranteed and depends on the selected compiler options).



#include <iostream>
#include <string>

void test(const std::string &value) { std::cout << "string overload: " << value << std::endl; }

//void test(const std::vector<std::string> &) { std::cout << "vector overload" << std::endl; }

int main()
{
test({ "one", "one" + 3 });
}


And you will get a valid result.



string overload: one


Pay attention to that this construction



{ "one", "two" }


is not an object of the type std::initializer_list<T>. This construction does not have a type. It is a braced-init-list that is used as an initialzer. Simply the compiler tries at first to use a constructor that have the first parameter of the type std::initializer_list to use with this initializer.



For example if you will use the class std::vector<const char *> then indeed the compiler will use its constructor with std::initializer_list and correspondingly initializes its parameter with this braced-init-list. For example



#include <iostream>
#include <vector>

int main()
{
std::vector<const char *> v( { "one", "two" } );

for ( const auto &s : v ) std::cout << s << ' ';
std::cout << 'n';
}





share|improve this answer























  • 4





    { "one", "one" + 3 } Doesn't this rely on the fact that both "one" are compiled to refer to the same address? Is this granted by standard?

    – Scheff
    13 hours ago








  • 1





    @Scheff It is written in my answer. Reread it.

    – Vlad from Moscow
    13 hours ago











  • Sorry, this catched my eye before I could read the rest. ;-) I myself am too paranoid to rely on that...

    – Scheff
    13 hours ago













  • @LightnessRacesinOrbit It depends on compiler options. Usually you can select the behavior of the compiler relative to string literals using compiler options.

    – Vlad from Moscow
    12 hours ago








  • 2





    Yep like -fno-merge-constants in GCC

    – Lightness Races in Orbit
    12 hours ago














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',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
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%2f57725075%2fstrange-behavior-of-stdinitializer-list-of-stdstrings%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









11















It calls



string(const char* b, const char* e) 


string ctor overload.



It works only if b and e points to the same string literal. Otherwise it is undefined behaviour.






share|improve this answer


























  • Yes, Thanks. Is there any idea how to achieve the choice of overloading with a vector, preferably without changing the syntax of the call?

    – Yuriy
    13 hours ago






  • 1





    I cannot find this overload in cppreference. What is it doing?

    – Yksisarvinen
    13 hours ago











  • Came to the same conclusion in a somehow funny way: Live Demo on coliru. Ok, ok, a debugger would've been even simpler - but I got a nice demonstration. ;-)

    – Scheff
    13 hours ago






  • 3





    @Yksisarvinen template< class InputIt > basic_string( InputIt first, InputIt last, const Allocator& alloc = Allocator() );

    – rafix07
    13 hours ago











  • @Yuriy What do you mean by "the choice of overloading with a vector"? What are you trying to do?

    – Lightness Races in Orbit
    13 hours ago
















11















It calls



string(const char* b, const char* e) 


string ctor overload.



It works only if b and e points to the same string literal. Otherwise it is undefined behaviour.






share|improve this answer


























  • Yes, Thanks. Is there any idea how to achieve the choice of overloading with a vector, preferably without changing the syntax of the call?

    – Yuriy
    13 hours ago






  • 1





    I cannot find this overload in cppreference. What is it doing?

    – Yksisarvinen
    13 hours ago











  • Came to the same conclusion in a somehow funny way: Live Demo on coliru. Ok, ok, a debugger would've been even simpler - but I got a nice demonstration. ;-)

    – Scheff
    13 hours ago






  • 3





    @Yksisarvinen template< class InputIt > basic_string( InputIt first, InputIt last, const Allocator& alloc = Allocator() );

    – rafix07
    13 hours ago











  • @Yuriy What do you mean by "the choice of overloading with a vector"? What are you trying to do?

    – Lightness Races in Orbit
    13 hours ago














11














11










11









It calls



string(const char* b, const char* e) 


string ctor overload.



It works only if b and e points to the same string literal. Otherwise it is undefined behaviour.






share|improve this answer













It calls



string(const char* b, const char* e) 


string ctor overload.



It works only if b and e points to the same string literal. Otherwise it is undefined behaviour.







share|improve this answer












share|improve this answer



share|improve this answer










answered 13 hours ago









rafix07rafix07

11.1k1 gold badge10 silver badges17 bronze badges




11.1k1 gold badge10 silver badges17 bronze badges
















  • Yes, Thanks. Is there any idea how to achieve the choice of overloading with a vector, preferably without changing the syntax of the call?

    – Yuriy
    13 hours ago






  • 1





    I cannot find this overload in cppreference. What is it doing?

    – Yksisarvinen
    13 hours ago











  • Came to the same conclusion in a somehow funny way: Live Demo on coliru. Ok, ok, a debugger would've been even simpler - but I got a nice demonstration. ;-)

    – Scheff
    13 hours ago






  • 3





    @Yksisarvinen template< class InputIt > basic_string( InputIt first, InputIt last, const Allocator& alloc = Allocator() );

    – rafix07
    13 hours ago











  • @Yuriy What do you mean by "the choice of overloading with a vector"? What are you trying to do?

    – Lightness Races in Orbit
    13 hours ago



















  • Yes, Thanks. Is there any idea how to achieve the choice of overloading with a vector, preferably without changing the syntax of the call?

    – Yuriy
    13 hours ago






  • 1





    I cannot find this overload in cppreference. What is it doing?

    – Yksisarvinen
    13 hours ago











  • Came to the same conclusion in a somehow funny way: Live Demo on coliru. Ok, ok, a debugger would've been even simpler - but I got a nice demonstration. ;-)

    – Scheff
    13 hours ago






  • 3





    @Yksisarvinen template< class InputIt > basic_string( InputIt first, InputIt last, const Allocator& alloc = Allocator() );

    – rafix07
    13 hours ago











  • @Yuriy What do you mean by "the choice of overloading with a vector"? What are you trying to do?

    – Lightness Races in Orbit
    13 hours ago

















Yes, Thanks. Is there any idea how to achieve the choice of overloading with a vector, preferably without changing the syntax of the call?

– Yuriy
13 hours ago





Yes, Thanks. Is there any idea how to achieve the choice of overloading with a vector, preferably without changing the syntax of the call?

– Yuriy
13 hours ago




1




1





I cannot find this overload in cppreference. What is it doing?

– Yksisarvinen
13 hours ago





I cannot find this overload in cppreference. What is it doing?

– Yksisarvinen
13 hours ago













Came to the same conclusion in a somehow funny way: Live Demo on coliru. Ok, ok, a debugger would've been even simpler - but I got a nice demonstration. ;-)

– Scheff
13 hours ago





Came to the same conclusion in a somehow funny way: Live Demo on coliru. Ok, ok, a debugger would've been even simpler - but I got a nice demonstration. ;-)

– Scheff
13 hours ago




3




3





@Yksisarvinen template< class InputIt > basic_string( InputIt first, InputIt last, const Allocator& alloc = Allocator() );

– rafix07
13 hours ago





@Yksisarvinen template< class InputIt > basic_string( InputIt first, InputIt last, const Allocator& alloc = Allocator() );

– rafix07
13 hours ago













@Yuriy What do you mean by "the choice of overloading with a vector"? What are you trying to do?

– Lightness Races in Orbit
13 hours ago





@Yuriy What do you mean by "the choice of overloading with a vector"? What are you trying to do?

– Lightness Races in Orbit
13 hours ago













6















For starters there is no used the constructor that accepts an initializer list because such a constructor looks like



basic_string(initializer_list<charT>, const Allocator& = Allocator());
^^^^^


So the compiler searches another appropriate constructor and it finds such a constructor. It is the constructor



template<class InputIterator>
basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator());


That is the expressions "one" and "two" are considered as iterators of the type const char *.



So the function test has undefined behavior.



You could write for example (provided that string literals with the same content are stored as one string literal in memory, which is not guaranteed and depends on the selected compiler options).



#include <iostream>
#include <string>

void test(const std::string &value) { std::cout << "string overload: " << value << std::endl; }

//void test(const std::vector<std::string> &) { std::cout << "vector overload" << std::endl; }

int main()
{
test({ "one", "one" + 3 });
}


And you will get a valid result.



string overload: one


Pay attention to that this construction



{ "one", "two" }


is not an object of the type std::initializer_list<T>. This construction does not have a type. It is a braced-init-list that is used as an initialzer. Simply the compiler tries at first to use a constructor that have the first parameter of the type std::initializer_list to use with this initializer.



For example if you will use the class std::vector<const char *> then indeed the compiler will use its constructor with std::initializer_list and correspondingly initializes its parameter with this braced-init-list. For example



#include <iostream>
#include <vector>

int main()
{
std::vector<const char *> v( { "one", "two" } );

for ( const auto &s : v ) std::cout << s << ' ';
std::cout << 'n';
}





share|improve this answer























  • 4





    { "one", "one" + 3 } Doesn't this rely on the fact that both "one" are compiled to refer to the same address? Is this granted by standard?

    – Scheff
    13 hours ago








  • 1





    @Scheff It is written in my answer. Reread it.

    – Vlad from Moscow
    13 hours ago











  • Sorry, this catched my eye before I could read the rest. ;-) I myself am too paranoid to rely on that...

    – Scheff
    13 hours ago













  • @LightnessRacesinOrbit It depends on compiler options. Usually you can select the behavior of the compiler relative to string literals using compiler options.

    – Vlad from Moscow
    12 hours ago








  • 2





    Yep like -fno-merge-constants in GCC

    – Lightness Races in Orbit
    12 hours ago
















6















For starters there is no used the constructor that accepts an initializer list because such a constructor looks like



basic_string(initializer_list<charT>, const Allocator& = Allocator());
^^^^^


So the compiler searches another appropriate constructor and it finds such a constructor. It is the constructor



template<class InputIterator>
basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator());


That is the expressions "one" and "two" are considered as iterators of the type const char *.



So the function test has undefined behavior.



You could write for example (provided that string literals with the same content are stored as one string literal in memory, which is not guaranteed and depends on the selected compiler options).



#include <iostream>
#include <string>

void test(const std::string &value) { std::cout << "string overload: " << value << std::endl; }

//void test(const std::vector<std::string> &) { std::cout << "vector overload" << std::endl; }

int main()
{
test({ "one", "one" + 3 });
}


And you will get a valid result.



string overload: one


Pay attention to that this construction



{ "one", "two" }


is not an object of the type std::initializer_list<T>. This construction does not have a type. It is a braced-init-list that is used as an initialzer. Simply the compiler tries at first to use a constructor that have the first parameter of the type std::initializer_list to use with this initializer.



For example if you will use the class std::vector<const char *> then indeed the compiler will use its constructor with std::initializer_list and correspondingly initializes its parameter with this braced-init-list. For example



#include <iostream>
#include <vector>

int main()
{
std::vector<const char *> v( { "one", "two" } );

for ( const auto &s : v ) std::cout << s << ' ';
std::cout << 'n';
}





share|improve this answer























  • 4





    { "one", "one" + 3 } Doesn't this rely on the fact that both "one" are compiled to refer to the same address? Is this granted by standard?

    – Scheff
    13 hours ago








  • 1





    @Scheff It is written in my answer. Reread it.

    – Vlad from Moscow
    13 hours ago











  • Sorry, this catched my eye before I could read the rest. ;-) I myself am too paranoid to rely on that...

    – Scheff
    13 hours ago













  • @LightnessRacesinOrbit It depends on compiler options. Usually you can select the behavior of the compiler relative to string literals using compiler options.

    – Vlad from Moscow
    12 hours ago








  • 2





    Yep like -fno-merge-constants in GCC

    – Lightness Races in Orbit
    12 hours ago














6














6










6









For starters there is no used the constructor that accepts an initializer list because such a constructor looks like



basic_string(initializer_list<charT>, const Allocator& = Allocator());
^^^^^


So the compiler searches another appropriate constructor and it finds such a constructor. It is the constructor



template<class InputIterator>
basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator());


That is the expressions "one" and "two" are considered as iterators of the type const char *.



So the function test has undefined behavior.



You could write for example (provided that string literals with the same content are stored as one string literal in memory, which is not guaranteed and depends on the selected compiler options).



#include <iostream>
#include <string>

void test(const std::string &value) { std::cout << "string overload: " << value << std::endl; }

//void test(const std::vector<std::string> &) { std::cout << "vector overload" << std::endl; }

int main()
{
test({ "one", "one" + 3 });
}


And you will get a valid result.



string overload: one


Pay attention to that this construction



{ "one", "two" }


is not an object of the type std::initializer_list<T>. This construction does not have a type. It is a braced-init-list that is used as an initialzer. Simply the compiler tries at first to use a constructor that have the first parameter of the type std::initializer_list to use with this initializer.



For example if you will use the class std::vector<const char *> then indeed the compiler will use its constructor with std::initializer_list and correspondingly initializes its parameter with this braced-init-list. For example



#include <iostream>
#include <vector>

int main()
{
std::vector<const char *> v( { "one", "two" } );

for ( const auto &s : v ) std::cout << s << ' ';
std::cout << 'n';
}





share|improve this answer















For starters there is no used the constructor that accepts an initializer list because such a constructor looks like



basic_string(initializer_list<charT>, const Allocator& = Allocator());
^^^^^


So the compiler searches another appropriate constructor and it finds such a constructor. It is the constructor



template<class InputIterator>
basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator());


That is the expressions "one" and "two" are considered as iterators of the type const char *.



So the function test has undefined behavior.



You could write for example (provided that string literals with the same content are stored as one string literal in memory, which is not guaranteed and depends on the selected compiler options).



#include <iostream>
#include <string>

void test(const std::string &value) { std::cout << "string overload: " << value << std::endl; }

//void test(const std::vector<std::string> &) { std::cout << "vector overload" << std::endl; }

int main()
{
test({ "one", "one" + 3 });
}


And you will get a valid result.



string overload: one


Pay attention to that this construction



{ "one", "two" }


is not an object of the type std::initializer_list<T>. This construction does not have a type. It is a braced-init-list that is used as an initialzer. Simply the compiler tries at first to use a constructor that have the first parameter of the type std::initializer_list to use with this initializer.



For example if you will use the class std::vector<const char *> then indeed the compiler will use its constructor with std::initializer_list and correspondingly initializes its parameter with this braced-init-list. For example



#include <iostream>
#include <vector>

int main()
{
std::vector<const char *> v( { "one", "two" } );

for ( const auto &s : v ) std::cout << s << ' ';
std::cout << 'n';
}






share|improve this answer














share|improve this answer



share|improve this answer








edited 12 hours ago

























answered 13 hours ago









Vlad from MoscowVlad from Moscow

152k14 gold badges92 silver badges195 bronze badges




152k14 gold badges92 silver badges195 bronze badges











  • 4





    { "one", "one" + 3 } Doesn't this rely on the fact that both "one" are compiled to refer to the same address? Is this granted by standard?

    – Scheff
    13 hours ago








  • 1





    @Scheff It is written in my answer. Reread it.

    – Vlad from Moscow
    13 hours ago











  • Sorry, this catched my eye before I could read the rest. ;-) I myself am too paranoid to rely on that...

    – Scheff
    13 hours ago













  • @LightnessRacesinOrbit It depends on compiler options. Usually you can select the behavior of the compiler relative to string literals using compiler options.

    – Vlad from Moscow
    12 hours ago








  • 2





    Yep like -fno-merge-constants in GCC

    – Lightness Races in Orbit
    12 hours ago














  • 4





    { "one", "one" + 3 } Doesn't this rely on the fact that both "one" are compiled to refer to the same address? Is this granted by standard?

    – Scheff
    13 hours ago








  • 1





    @Scheff It is written in my answer. Reread it.

    – Vlad from Moscow
    13 hours ago











  • Sorry, this catched my eye before I could read the rest. ;-) I myself am too paranoid to rely on that...

    – Scheff
    13 hours ago













  • @LightnessRacesinOrbit It depends on compiler options. Usually you can select the behavior of the compiler relative to string literals using compiler options.

    – Vlad from Moscow
    12 hours ago








  • 2





    Yep like -fno-merge-constants in GCC

    – Lightness Races in Orbit
    12 hours ago








4




4





{ "one", "one" + 3 } Doesn't this rely on the fact that both "one" are compiled to refer to the same address? Is this granted by standard?

– Scheff
13 hours ago







{ "one", "one" + 3 } Doesn't this rely on the fact that both "one" are compiled to refer to the same address? Is this granted by standard?

– Scheff
13 hours ago






1




1





@Scheff It is written in my answer. Reread it.

– Vlad from Moscow
13 hours ago





@Scheff It is written in my answer. Reread it.

– Vlad from Moscow
13 hours ago













Sorry, this catched my eye before I could read the rest. ;-) I myself am too paranoid to rely on that...

– Scheff
13 hours ago







Sorry, this catched my eye before I could read the rest. ;-) I myself am too paranoid to rely on that...

– Scheff
13 hours ago















@LightnessRacesinOrbit It depends on compiler options. Usually you can select the behavior of the compiler relative to string literals using compiler options.

– Vlad from Moscow
12 hours ago







@LightnessRacesinOrbit It depends on compiler options. Usually you can select the behavior of the compiler relative to string literals using compiler options.

– Vlad from Moscow
12 hours ago






2




2





Yep like -fno-merge-constants in GCC

– Lightness Races in Orbit
12 hours ago





Yep like -fno-merge-constants in GCC

– Lightness Races in Orbit
12 hours ago


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f57725075%2fstrange-behavior-of-stdinitializer-list-of-stdstrings%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Hudson River Historic District Contents Geography History The district today Aesthetics Cultural...

The number designs the writing. Feandra Aversely Definition: The act of ingrafting a sprig or shoot of one...

Ayherre Geografie Demografie Externe links Navigatiemenu43° 23′ NB, 1° 15′ WL43° 23′ NB, 1°...