Почему при инициализации карты невозможно опустить фигурные скобки?

Вдохновленный этим ответом, я попробовал следующий пример:

#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 ожидает набор отдельных объектов, каждый из которых содержит ключ и пару значений.

Наличие единого списка отдельных элементов не имеет смысла, и его также трудно читать (чтобы убедиться, что у вас есть несколько элементов, которые точно делятся на два).