Ответ 1
Великие мысли тоже думают; v). Я представил отчет о дефектах и предложил изменить стандарт на эту тему.
http://cplusplus.github.com/LWG/lwg-active.html#2089
Кроме того, Люк Дантон помог мне понять сложность: Прямая или стандартная инициализация в std:: allocator.
Когда EmplaceConstructible (23.2.1 [container.requirements.general]/13) для инициализации используется возникает объект с прямой инициализацией. Инициализация агрегата или использование конструктора std:: initializer_list с emplace требует именования инициализированный тип и перемещение временного. Это результат std:: allocator:: construct using direct-initialization, not list-initialization (иногда называемая "равномерной инициализацией" ) синтаксис.
Изменение std:: allocator:: construct для использования инициализации списка будет, среди прочего, отдавать предпочтение std:: initializer_list перегрузки конструктора, нарушение действующего кода в неинтуитивном и неприменимый способ - для emplace_back не будет доступа для доступа к конструктор, вытесненный std:: initializer_list, без существенного повторное выполнение push_back.
std::vector<std::vector<int>> v; v.emplace_back(3, 4); // v[0] == {4, 4, 4}, not {3, 4} as in list-initialization
Предлагаемый компромисс заключается в использовании SFINAE с std:: is_constructible, который проверяет правильность формирования прямой инициализации. Если is_constructible является ложным, тогда альтернатива std:: allocator:: конструкция перегрузки выбрана, которая использует Список инициализация. Поскольку инициализация списка всегда возвращается к прямая инициализация, пользователь увидит диагностические сообщения, как будто инициализация списка (унифицированная инициализация) всегда использовалась, потому что перегрузка с прямой инициализацией не может потерпеть неудачу.
Я вижу два угловых случая, которые открывают пробелы в этой схеме. Один происходит когда аргументы, предназначенные для std:: initializer_list, удовлетворяют конструктор, такой как попытка вставления - вставить значение {3, 4} в выше пример. Обходной путь состоит в том, чтобы явно указать std:: initializer_list, как в v.emplace_back (std:: initializer_list (3, 4)). Поскольку это соответствует семантика, как если бы был выведен std:: initializer_list, кажется, что здесь не будет настоящей проблемы.
В другом случае аргументы, предназначенные для агрегатной инициализации удовлетворяют конструктору. Поскольку агрегаты не могут быть определены пользователем конструкторов, это требует, чтобы первый нестатический член данных совокупность неявно конвертируется из совокупного типа и что список инициализаторов имеет один элемент. Обходной путь поставьте инициализатор для второго элемента. По-прежнему невозможно на месте построить совокупность с одним нестатическим элементом данных посредством преобразование из типа, конвертируемого в собственный тип агрегата. Эта кажется приемлемой маленькой дырой.