Использование лямбда в инициализаторе по умолчанию gcc vs clang

#include <cassert>
#include <cmath>

int main()
{
    struct point_of_cone
    {
        double x, y;
        double z = [&] { using std::sqrt; return sqrt(x * x + y * y); }();
    };
    point_of_cone p = {3.0, 4.0};
    assert(p.z == 5.0);
}

Работает нормально для clang++ из магистрали, но для g++ из магистрали происходит сбой с сообщением об ошибке (ссылка):

ошибка: «это» не было захвачено для этой лямбда-функции

Определение point_of_cone в области пространства имен отлично работает для обоих.

Слегка измененное определение с [this] лямбда-захватом прекрасно работает как в глобальной, так и в локальной области.

Какой компилятор прав?


person Tomilov Anatoliy    schedule 18.10.2016    source источник
comment
разместите этот код в своем вопросе, пожалуйста   -  person xaxxon    schedule 18.10.2016
comment
@Orient Нет, я имел в виду ссылку xaxxon на Godbolt, где он установил неправильный флаг.   -  person Columbo    schedule 18.10.2016
comment
Хм, вопрос в том, должен ли [&] захватить this. Не уверен насчет новых стандартов, но ответ здесь предполагает, что нет: заголовок stackoverflow.com/questions/16323032/   -  person Hayt    schedule 18.10.2016
comment
@Хайт, это другое.   -  person xaxxon    schedule 18.10.2016
comment
@xaxxon, где имеется в виду [&this]? Я имел в виду, будет ли захват по умолчанию [&] включать this или нет.   -  person Hayt    schedule 18.10.2016
comment
@Hayt Если лямбда-захват включает захват по умолчанию, который равен &, никакому идентификатору в простом захвате этого лямбда-захвата не должен предшествовать символ &. Если лямбда-захват включает в себя захват-по умолчанию =, каждый простой захват этого лямбда-захвата должен иметь форму «идентификатор &» или «* это». [Примечание: форма [&,this] избыточна, но принята для совместимости с ISO C++ 2014. — примечание в конце] Я не совсем понимаю весь этот раздел, но комментарий ясно дает понять, что [ &] фиксирует это   -  person xaxxon    schedule 18.10.2016
comment
Да, я тоже не был уверен в этом, но это, кажется, указывает на то, что [&] должен это зафиксировать.   -  person Hayt    schedule 18.10.2016
comment
@ориент, почему вы удалили комментарий с фактическим исходным кодом, который воспроизводит ошибку, не отредактировав свой вопрос, чтобы включить его?   -  person xaxxon    schedule 18.10.2016
comment
@xaxxon Ссылка была помещена в основной текст вопроса, как вы и предлагали.   -  person Tomilov Anatoliy    schedule 18.10.2016
comment
@xaxxon Лучше опубликовать весь код по ссылке?   -  person Tomilov Anatoliy    schedule 18.10.2016
comment
@Orient ваш вопрос должен содержать весь код, необходимый для воспроизведения вашего вопроса.   -  person xaxxon    schedule 18.10.2016
comment
@xaxxon Готово.   -  person Tomilov Anatoliy    schedule 18.10.2016
comment
@Orient, спасибо :) Это помогает другим людям, у которых есть проблема, быстрее узнать, есть ли у них такая же проблема или нет. И вопрос по-прежнему хорош, даже если ссылка на вопрос по какой-то причине умирает.   -  person xaxxon    schedule 18.10.2016
comment
(Оператор в утверждении опасен - 4.0 можно точно представить...)   -  person greybeard    schedule 11.11.2016
comment
@greybeard 3.0, 4.0 и 5.0 имеют точное представление. Нет проблем. Сравнение с толерантностью может усложнить пример.   -  person Tomilov Anatoliy    schedule 11.11.2016
comment
There is no problem, как и в 9.0, 16.0, 25.0, имеют точные представления, и результат std::sqrt(25.0) гарантированно будет точным? Мне нужно будет прочитать о C ++, если и когда возникнет необходимость.   -  person greybeard    schedule 11.11.2016
comment
@greybeard Думаю, речь идет об IEEE 754.   -  person Tomilov Anatoliy    schedule 11.11.2016
comment
Это действительно потребовало бы точности - раньше это была единственная функция в дополнение к операторам с такими ограничениями, похоже, с тех пор к ней присоединился плавный умножить-сложение. (И может предложить использовать hypot().)   -  person greybeard    schedule 11.11.2016
comment
@greybeard Что ты думаешь? Должен ли я изменить double на int, чтобы сделать пример лучше?   -  person Tomilov Anatoliy    schedule 11.11.2016
comment
(от небрежного замечания к такой хитрости) Should I change double to int to make example better? Или вообще взять другой пример, который не пытается сравнить результаты трансцендентных функций на равенство, поскольку пример иллюстрирует захват в лямбде и длину этого обмена о сравнении двойников на равенство. На заметку: hypot() избегает undue overflow or underflow at intermediate stages, но я не могу найти необходимую точность, эквивалентную sqrt().   -  person greybeard    schedule 11.11.2016


Ответы (1)


Это ошибка gcc.

int main() {
    struct A {
        int x, i = [&] { return x; }();
    } a{0};
}

Это не удается, но если мы…

  • изменить & на this или
  • объявить A как область пространства имен,

оно работает. Однако ни то, ни другое не должно влиять на правильность формы.

Сообщено: #78019.

person Columbo    schedule 18.10.2016
comment
Если это та же самая ошибка, с которой я недавно сталкивался несколько раз, то другой обходной путь — явно сказать this->. - person Griwes; 18.10.2016
comment
@Griwes Не могли бы вы использовать противопоставление, чтобы сделать вывод, что это не та ошибка, с которой вы столкнулись? :-) - person Columbo; 18.10.2016