Ответ 1
Я могу воспроизвести это, если не сделаю одно из следующих действий:
- удалить
const
изa
- name
a
в списке захвата - изменить
std::function<void(int)>
наauto
- сделать лямбда не общим, изменив
auto b
наint b
- используйте Clang (например, v3.5.0)
Я считаю, что это ошибка компилятора, связанная с оптимизацией, и неспособность обнаружить odr-использование в общей лямбда (хотя интересно, что установка -O0
не влияет). Это может быть связано с ошибка 61814, но я не думаю, что это одно и то же, поэтому:
Я поднял его как ошибка GCC 64791.
- (Обновление: эта ошибка с тех пор была отмечена как исправленная в GCC 5.0.)
Разумеется, я не могу найти ничего очевидного в формулировке С++ 14, которая должна запрещать ваш код, хотя в новой формулировке С++ 14 очень мало "очевидных".: (
[C++14: 5.1.2/6]:
[..] Для общей лямбда без лямбда-захвата тип замыкания имеет открытый не виртуальный не явный шаблон функции преобразования const для указателя на функцию. Шаблон функции преобразования имеет тот же изобретенный список параметров шаблона, и указатель на функцию имеет те же типы параметров, что и шаблон оператора вызова функции. [..]
[C++14: 5.1.2/12]:
Лямбда-выражение с ассоциированным захватом-умолчанию, которое явно не фиксирует эту или переменную с автоматической продолжительностью хранения (это исключает любое идентификатор-выражение, которое, как было установлено, ссылается на связанный с init-capture, статический элемент данных), называется неявным захватом объекта (т.е.this
или переменной), если составной оператор:
- odr использует (3.2) объект или
- обозначает объект в потенциально вычисленном выражении (3.2), где охватывающее полное выражение зависит от общего параметра лямбда, объявленного в пределах области охвата лямбда-выражения.
[Пример:
void f(int, const int (&)[2] = {}) { } // #1 void f(const int&, const int (&)[1]) { } // #2 void test() { const int x = 17; auto g = [](auto a) { f(x); // OK: calls #1, does not capture x }; auto g2 = [=](auto a) { int selector[sizeof(a) == 1 ? 1 : 2]{}; f(x, selector); // OK: is a dependent expression, so captures x }; }
-end example] Все такие неявно захваченные объекты должны быть объявлены в пределах охвата лямбда-выражения. [Примечание. Неявный захват объекта вложенным лямбда-выражением может вызвать его неявный захват с помощью содержащего лямбда-выражения (см. Ниже). Неявное использование odr этого может привести к неявному захвату. -end note]
[C++14: 5.1.2/13]:
Объект захватывается, если он зафиксирован явно или неявно. Объект, захваченный лямбда-выражением, используется odr (3.2) в области, содержащей лямбда-выражение. [..]