Правильный ответ - Джонатан Уэйли. Я оставлю это, поскольку он предоставляет полезную информацию для людей, у которых есть аналогичная проблема, связанная с insert
.
Короткая версия, что это вызвано проблемой в реализации стандартной библиотеки, используемой GCC 4.7.2, в результате чего из вводящей в заблуждение формулировки, используемые в C++ 11 Стандарт на. Существует предложение об изменении формулировки, а также исправление реализации в GCC 4.8.
Длинная версия
This GCC bug entry сообщает очень похожий вопрос, где insert
используется вместо emplace
. LibstdC++ реализация из insert
следует стандарт, в котором говорится о insert
функции (в частности, template <class P> pair<iterator,bool> insert(P&& obj)
):
(§23.5.4.4/5) Примечания: Эта подпись не будет участвовать в разрешении перегрузки, если P не является неявно конвертируемым до value_type
.
libstdC++ кажется, реализовали это требование, используя enable_if
заявление, которое проверяет std::is_convertible<>
для типов участвующих.
Отчет об ошибке, упомянутый выше, гласит, что действительно необходимо использовать std::is_constructible<>
, а формулировку в Стандарте следует изменить. Он связывает с ПРГ (язык рабочей группы) вопросом, в котором предлагается изменение к Стандарту для этого уже (LWG issue #2005, увидеть Portland 2012 записи, соответствующую часть предлагаемого изменения ниже):
Изменение 23.5.4.4 [unord.map.modifers] на стр. 1, как показано:
template <class P>
pair<iterator, bool> insert(P&& obj);
[...] Примечание: Эта подпись не должна участвовать в разрешении перегрузки, если P не
неявно конвертируются в VALUE_TYPE
std::is_constructible<value_type, P&&>::value
верно.
Предлагаемое изменение также утверждает, что действие функции insert
описанного выше должно быть эквивалентна emplace(std::forward<P>(obj))
. Поэтому, вероятно, можно с уверенностью сказать, что проблема, описанная в вашем вопросе, является точно такой же проблемой.
И действительно, предложенные изменения, как представляются, отражен в последних GCC 4.8 снимок: При компиляции коды с GCC 4.8, то is_convertible
проверка не выполняется и не появляется сообщений об ошибке.
Закрыть, но нет сигары :) LWG 2005 применяется только к 'insert' not' emplace', причина, по которой программа выходит из строя с GCC 4.7.2, заключается в том, что она не выполняет проверку доступа как часть вывода аргумента шаблона (as требуется в C++ 03), поэтому 'is_constructible' получает отказ доступа из-за частного конструктора. GCC 4.8 реализует правила C++ 11 и проверяет доступ во время вывода аргумента шаблона. –
. Вы можете подтвердить разницу не из-за каких-либо изменений в стандартной библиотеке путем предварительной обработки кода с помощью G ++ 4.7 (поэтому он использует библиотеку из 4.7), а затем компилирует это с 4.8, и в этом случае программа работает, доказывая, что это был компилятор, а не библиотека, которая изменилась –