Я думаю, что открытый CWG выпуск 2058 здесь важен для определения правильности вашей программы.
В соответствии с нынешней формулировкой стандарта, я думаю, что ваша программа неправильно сформирован.
На основе стандарта C ++ 17 (окончательный вариант):
Согласно [basi c .link] / 6 декларации в вашей лямбде будет объявлено theRealCallback
с внешней связью , потому что это объявление функции в области видимости блока, которое не соответствует какой-либо другой, уже объявленной сущности.
В то же время время согласно [basi c .link] /4.2 второе объявление theRealCallback
имеет внутреннюю связь , поскольку это объявление области имен пространства функций в безымянном пространстве имен.
Согласно [basi c .link] / 6 программа плохо сформирована, если она объявляет сущность с внутренними и внешними связями в одной и той же единице перевода. Эта неправильная форма была добавлена только недавно, в качестве разрешения CWG, выпуск 426 .
Как упоминалось в примечаниях к CWG, выпуск 426, согласно [basi c .link] / 9 , объявления ссылаются только на одну и ту же сущность, хотя, если они имеют одинаковую связь, то есть условие неформальности в ее резолюции не применяется.
Так что если мы интерпретируйте это строго, тогда программа действительно имеет две независимые функции void theRealCallback()
, одна с внешней и одна с внутренней связью. Тот, у которого есть внутренняя связь, имеет определение, а тот, у которого нет внешней связи. В этом случае программа нарушает правило одного определения, поскольку при вызове theRealCallback();
в лямбда-ODR используется функция с внешней связью, у которой нет определения. Это сделало бы программу некорректной, диагностика не требовалась c.
Хотя это, вероятно, правильное толкование при строгом чтении стандарта, я думаю, что решение проблемы CWG 426 предназначалось для применения здесь потому что с интерпретацией выше это никогда не будет применяться. Я не знаю, почему упомянутая проблема не была исправлена в резолюции.
Если проблема 1058 * CWG 2058 должна быть решена, чтобы сказать, что объявление в области видимости блока будет соответствовать связи окружающего пространства имен, тогда программа будет правильно сформирована, а theRealCallback
будет иметь внутреннюю связь.
Вы можете видеть, что G CC считает программу плохо сформированной, если стандарт интерпретируется строго путем добавления флага -pedantic-errors
, который заставит его выдавать ошибку, а не предупреждение.
Конечно, самое простое решение, позволяющее обойти эту проблему, - это объявить вперед void theRealCallback();
вне лямбды в области пространства имен, в этом случае связь определенно является внутренней, и любое объявление области блока будет ссылаться на это объявление, принимая его связь.
Это не проблема, если пространство имен именуется, потому что тогда объявление области имен будет иметь внешнюю связь.