корректности этого кода. MSVC считает, что всё хорошо. GCC не позволяет из тела лямбды вызвать нешаблонный operator(), но позволяет вызвать шаблонный (очевидно, это следствие того, как реализован оператор каста к указателю на функцию). Clang же не позволяет вызвать ни тот, ни другой
>> The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type
>> The closure type for a lambda-expression has a public inline function call operator (for a non-generic lambda) or function call operator template (for a generic lambda)
>> An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than by changing
— ...
( http://eel.is/c++draft/expr.prim.lambda#closure-1 )
Ни в последнем процитированном пункте, ни во всём разделе, я не нашёл никаких исключений, касающихся name lookup для лямбд без захвата, т.е. поиск имён в лямбде должен соответствовать поиску имён внутри unnamed non-union class type, а значит, можно предположить, что в следующем куске кода поведение при вызове f(3) и l(3) должно быть эквивалентно:
struct /* unnamed */ {
template<typename Auto>
constexpr int operator()(Auto n) const {
if (n <= 1) return 1;
else return n * operator()(n-1);
}
} f;
void foo() {
constexpr auto l = [](auto n) -> int {
if (n <= 1) return 1;
else return n * operator()(n-1);
};
static_assert(l(3) == f(3));
};
При этом, кажется, при нешаблонном operator() и GCC, и MSVC оба могут быть правы, допускаю даже, что могут быть правы одновременно. Но я не вижу ни одного аргумента в пользу Clang, который не позволяет вызвать шаблонный operator() вообще
Быть может, у кого-то есть мысли на этот счёт?
В приведённых тобой цитатах нет ничего про то как оно должно работать изнутри лямбды
Судя по тому, сколько грабель было сломано и пропозалов написано, рекурсивные лямбды невозможно реализовать средствами текущего стандарта. Обычно делают хелпер, который оборачивает любую лямбду, добавляя в неё первым аргументом auto self
В каком смысле невозможно реализовать рекурсивную лямбду? Это довольно-таки несложно
Покажи, если несложно. Очевидно, что вариант с std::function, хелпер-функциями/классами не считается "чистым"
Ну если так, то, видимо, нельзя. Однако это какая-то непрактичная "чистота"
Почему непрактичная-то? Если мне нужна рекурсивная функция, то аналогично мне может быть нужна рекурсивная лямбда без каких-то доп. ограничений
Рекурсивная лямбда – довольно странная необходимость, но если уже что-то понадобилось, то вопрос за каким-то оверхедом вряд ли стоит
Это не странная необходимость. Рекурсивный визитор для какой-нибудь древовидной структуры - навскидку
Обсуждают сегодня