3

std::vector‘s initializer list constructor has the form

vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );

What makes an initialization like std::vector<string> vec{ “foo”, “bar” }; possible? Why does the constructor accept an std::initializer_list<const char*>, even though the std::vectors‘s T is std::string? Where and how does the conversion from std::initializer_list<const char*>to std::initializer_list<string> happen?

3
  • 2
    Here's a way to solve this Smystery, all by yourself, and actually have a very beneficial learning experience: write this code, use your debugger to step into the vector's constructor, see which constructor gets called, and how exactly it goes about doing what it does. This is one of those questions that nobody needs to ask, since they can easily find the answer themselves using only a tool that every C++ developer must know how to use: a debugger. Did you try doing it? What did your debugger show you, as far as which constructor gets used for this? Commented Sep 5, 2022 at 19:53
  • 1
    I agree, but just in case you are using Visual Studio's debugger you will have to turn off the 'Just My Code' feature to do this. I believe it's on by default, and useful most of the time, but not here. Commented Sep 5, 2022 at 19:57
  • 2
    @SamVarshavchik Let's be fair, the debugger doesn't show anything here. My GDB just shows three std::string(const char *) constructors being called, and without knowing the theory, one can't tell if this is an initializer_list<const char *> being converted to an initializer_list<string>, or initializer_list<string> being constructed element-wise from pointers. Commented Sep 5, 2022 at 22:16

1 Answer 1

5

I think you should refer to this section of the C++ 17 Standard (11.6.4 List-initialization)

5 An object of type std::initializer_list is constructed from an initializer list as if the implementation generated and materialized (7.4) a prvalue of type “array of N const E”, where N is the number of elements in the initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer list, and the std::initializer_list object is constructed to refer to that array. [ Note: A constructor or conversion function selected for the copy shall be accessible (Clause 14) in the context of the initializer list. — end note ] If a narrowing conversion is required to initialize any of the elements, the program is ill-formed. [ Example:

struct X {
X(std::initializer_list<double> v);
};
X x{ 1,2,3 };

The initialization will be implemented in a way roughly equivalent to this:

const double __a[3] = {double{1}, double{2}, double{3}};
X x(std::initializer_list<double>(__a, __a+3));

assuming that the implementation can construct an initializer_list object with a pair of pointers. — end example ]

Pay attention to that there is the conversion constructor for the class std::basic_string

basic_string(const charT* s, const Allocator& a = Allocator());

So in this declaration

std::vector<string> vec{ “foo”, “bar” };

at first an object of the type std::initializer_list<std::string> is constructed from the initializer list and then is used as an initializer for the vector of the type std::vector<std::string>.

If instead you will write

std::initializer_list<const char *> lst = { "foo", "bar" };
std::vector<std::string> vec( lst );

then the compiler will issue an error because there is no implicit conversion from the type std::initializer_list<const char *> to the type std::initializer_list<std::string>.

That is the compiler determines whether it can build std::initializer_list from a braced initializer list to call the initializer-list constructor.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.