Обновлено: мое замешательство произошло из-за непонимания спецификатора explicit и контекстных преобразований в bool
В версии 19.35 вы могли передать вызываемый объект ranges::views::filter, который возвращал std::optional. В v19.36 нельзя:
https://godbolt.org/z/jcfjE3var
auto input = std::vector<std::optional<int>>{};
#if 1
// broken v19.36, works prior
input | ranges::views::filter([](auto pair) -> std::optional<int> { return pair; });
#else
// works
input | ranges::views::filter([](auto pair) -> bool { return pair; });
#endif
Кто-нибудь знает, почему?
Вы можете добавить два компилятора в godbolt, чтобы вы могли видеть, что 19.35 принимает и 19.latest отклоняет один и тот же код рядом: godbolt.org/z/6ndr6TKz1
Когда код ломается после обновления или смены компилятора, мой опыт подсказывает мне, что обычно это происходит из-за неопределенного поведения в коде, который только что оказался работающим со старым компилятором, или (редко) это вызвано ошибкой в новый (или старый) компилятор, из-за которого он не смог собрать код (или неправильно принял его ранее).
Я понятия не имею, почему это так (таким образом, комментарий, а не ответ). Но если вы измените лямбду на: return pair.second.has_value(), то она тоже скомпилируется на 19.latest.
@Frodyne, у тебя работает мой код, поэтому ты должен был дать ответ. Но теперь я изменил вопрос. Только Бог знает, почему ranges::views::filter смог принять T -> std::optional в первую очередь
std::optional контекстуально преобразуется в bool благодаря оператору operator bool().
@TomHuntington Я пытаюсь найти четкое определение того, чем ограничивается «предикат», например. вызываемый параметр для filter, но я не могу его найти. Только T -> bool?
@dfrib range-v3 имеет собственную концепцию для std::indirect_unary_predicate<Fn, Iterator> . Кажется, что это понятие уже не проходит. Я пытался поиграться, но не смог заставить его работать





input | ranges::views::filter([](auto pair) -> bool { return pair; }); не работает, потому что std::optional<int>& нельзя неявно преобразовать в bool. Причина, по которой это работает, заключается в том, что вы на самом деле не используете тело функции, потому что вы не выполняете итерацию по представлению. [](std::optional<int> pair) -> bool { return pair; } сразу показывает ошибку.
Вот почему лямбда [](auto pair) -> std::optional<int> тоже не работает: чтобы быть допустимым предикатом для filter, тип возвращаемого значения должен быть булевым тестом, что требует неявной конвертации в bool.
Вам нужно что-то вроде этого:
input | ranges::views::filter([](auto pair) { return bool(pair); })
@TomHuntington Ссылка на Godbolt, которую вы дали, показывает, что она не работает, я не думаю, что это когда-либо работало. Это просто неправильно сформировано, потому что нет неявного преобразования из опционального в логическое. Также я выяснил, почему предыдущие версии принимали функторы, производящие необязательно: библиотека ranges-v3 ranges::predicate была сломана godbolt.org/z/7qcs9Yrx3
Итак, я понимаю, что [](std::optional<T> o) -> bool { return o; } никогда не работал. Тем не менее я не уверен, почему [](std::optional<T> o) -> std::optional<T> { return o; } раньше работал
"ranges::predicate библиотеки ranges-v3 не работает" спасибо
Теперь я понимаю спецификатор explicit и контекстные преобразования в bool. en.cppreference.com/w/cpp/language/… О c++, зачем ты так со мной.
пожалуйста, включите минимальный воспроизводимый пример и сообщение об ошибке компилятора в вопросе