В С++ 11 кажется допустимым инициализировать std::map<std::string, int>
следующим образом:
std::map<std::string, int> myMap = {
{ "One", 1 },
{ "Two", 2 },
{ "Three", 3 }
};
Интуитивно это имеет смысл — инициализатор, заключенный в фигурные скобки, представляет собой список пар строк, а std::map<std::string, int>::value_type
— это std::pair<std::string, int>
(возможно, с некоторыми уточнениями const
.
Однако я не уверен, что понимаю, как здесь работает набор текста. Если мы исключим здесь объявление переменной и оставим только инициализатор, заключенный в фигурные скобки, компилятор не узнает, что он просматривает std::initializer_list<std::pair<std::string, int>>
, потому что он не будет знать, что пары в фигурных скобках представляют std::pair
s. Поэтому кажется, что компилятор каким-то образом откладывает действие по присвоению типа инициализатору, заключенному в фигурные скобки, до тех пор, пока он не получит достаточно информации о типе из конструктора std::map
, чтобы понять, что вложенные фигурные скобки предназначены для пар. Я не помню, чтобы что-то подобное происходило в C++03; насколько мне известно, тип выражения никогда не зависел от его контекста.
Какие языковые правила позволяют правильно компилировать этот код и компилятору определять, какой тип использовать для списка инициализаторов? Я надеюсь на ответы с конкретными ссылками на спецификацию С++ 11, так как очень интересно, что это работает!
Спасибо!
std::pair<std::string, int> myArray[]
), инициализированным с помощью фигурных скобок, за исключением того, что тип не назван напрямую, он выводится из доступных конструкторов. - person Ben Voigt   schedule 13.07.2014operator T()
) — это еще одно место, где контекст определяет тип выражения (и используется для разрешения перегрузки). - person Ben Voigt   schedule 13.07.2014braced-init-list
не является выражением и не имеет типа. Нет вывода, только разрешение перегрузки среди конструкторов списка инициализаторов (из которых есть только один) - person Cubbi   schedule 13.07.2014