In C++11, it seems like it's legal to initialize a std::map<std::string, int>
as follows:
std::map<std::string, int> myMap = {
{ "One", 1 },
{ "Two", 2 },
{ "Three", 3 }
};
Intuitively, this makes sense - the brace-enclosed initializer is a list of pairs of strings, and std::map<std::string, int>::value_type
is std::pair<std::string, int>
(possibly with some const
qualifications.
However, I'm not sure I understand how the typing works here. If we eliminate the variable declaration here and just have the brace-enclosed initializer, the compiler wouldn't know that it was looking at a std::initializer_list<std::pair<std::string, int>>
because it wouldn't know that the braced pairs represented std::pair
s. Therefore, it seems as though the compiler is somehow deferring the act of assigning a type to the brace-enclosed initializer until it has enough type information from the std::map
constructor to realize that the nested braces are for pairs. I don't remember anything like this happening in C++03; to the best of my knowledge, the type of an expression never depended on its context.
What language rules permit this code to compile correctly and for the compiler to determine what type to use for the initializer list? I'm hoping for answers with specific references to the C++11 spec, since it's really interesting that this works!
Thanks!
std::pair<std::string, int> myArray[]
) initialized using braces, except that the type isn't directly named, it's inferred from the available constructors. – Allweinoperator T()
) are the other place where the context determines the type of an expression (and is used for overload resolution). – Allweinbraced-init-list
is not an expression and has no type. There is no deduction, only overload resolution among the initializer-list constructors (of which there is only one) – Leone