Почему при инициализации карты невозможно опустить фигурные скобки?
Вдохновленный этим ответом, я попробовал следующий пример:
#include <map>
#include <string>
#include <iostream>
int main()
{
const std::map< int, std::string > mapping = {
1, "ONE",
2, "TWO",
};
const auto it = mapping.find( 1 );
if ( mapping.end() != it )
{
std::cout << it->second << std::endl;
}
else
{
std::cout << "not found!" << std::endl;
}
}
и компиляция завершилась неудачей со следующим сообщением об ошибке (g++ 4.6.1):
gh.cpp:11:5: error: could not convert '{1, "ONE", 2, "TWO"}' from '<brace-enclosed initializer list>' to 'const std::map<int, std::basic_string<char> >'
Я знаю, как это исправить:
const std::map< int, std::string > mapping = {
{1, "ONE"},
{2, "TWO"},
};
но почему компиляция завершилась неудачей в верхнем примере?
Ответы
Ответ 1
Поскольку карта является неагрегатной и содержит неагрегатные элементы (std::pair<key_type, mapped_type>
), для этого требуется список инициализаторов, полный списков инициализаторов, по одному для каждой пары.
std::pair<int,int> p0{ 1,2 }; // single pair
std::map<int, int> m { { 1,2 } }; // map with one element
std::map<int, int> m { { 1,2 }, { 3,4} }; // map with two elements
Имейте в виду, что правила для выравнивания фигур применяются к агрегатам, поэтому они не применяются здесь.
Ответ 2
В стандарте С++ 11 допускаются отклонения фигур только тогда, когда цель является совокупностью:
8.5.1 Агрегаты [dcl.init.aggr]
Агрегат - это массив или класс (раздел 9) без каких-либо пользовательских конструкторы (12.1), никакие логические или несимметричные инициализаторы для нестатических членов данных (9.2), нет частных или защищенных нестатических данных (Раздел 11), нет базовых классов (раздел 10) и нет виртуальных функций (10.3).
...
(Пункт 11)
В объявлении формы
T x = { a };
Скобки можно отбросить в списке инициализаторов следующим образом. Если Список инициализаторов начинается с левой скобки, затем следующая список инициализаторов-разделов, разделенных запятыми, инициализирует члены субагрегат; ошибочно, чтобы было больше initializer-clauses, чем члены. Если, однако, список инициализаторов для подзаголовка не начинается с левой скобки, тогда только достаточно инициализатор-предложения из списка, чтобы инициализировать члены подгруппы; любые оставшиеся условия инициализации слева, чтобы инициализировать следующий член совокупности, из которого текущий субагрегат является членом.
Ответ 3
Прошло много времени с тех пор, как я сделал С++, но я предполагаю, что std::map
ожидает набор отдельных объектов, каждый из которых содержит ключ и пару значений.
Наличие единого списка отдельных элементов не имеет смысла, и его также трудно читать (чтобы убедиться, что у вас есть несколько элементов, которые точно делятся на два).