Подтвердить что ты не робот

Is [] <typename>() {} действительное определение лямбда?

Я экспериментировал с lambdas и компиляторами из-за другого вопроса здесь, на SO.
Я только что понял (и это совершенно нормально), что следующий код действителен:

int main() {
    auto l = [](){};
    l.operator()();
}

Фактически стандарт говорит, что тип замыкания имеет открытый оператор вызова встроенной функции и т.д., поэтому имеет смысл активировать его.

То, что я не могу объяснить, посмотрев на стандарт (ну, рабочий проект), является тот факт, что GCC (6.1) компилирует следующий фрагмент кода (clang 3.9 не делает):

int main() {
    auto l = []<typename>(){};
    l.operator()<void>();
}

Нет предупреждений, ошибок нет. Это допустимый код или он должен быть отклонен компилятором?

4b9b3361

Ответ 1

В N4140 5.1.2 [expr.prim.lambda] лямбда-выражение определяется как

лямбда-вводчик лямбда-декларатор opt составное-утверждение

где "лямбда-интродьюсер" - это [], включающий необязательный "лямбда-захват", а "лямбда-декларатор опт " - это материал, начинающийся с "(параметр-объявление-предложение)".

[]<typename>(){}

не удовлетворяет этому требованию, потому что есть что-то между лямбда-представителем и лямбда-декларатором, поэтому оно не является допустимым лямбда-выражением

Таким образом, ваш пример кода недопустим C++ и должен быть отклонен компилятором.


Поскольку это также помечено , я просмотрел список расширений GNU C++. Я не нашел какого-либо расширения, которое сделало бы рассматриваемый синтаксис легальным в GNU C++.

Однако, согласно Разделу 4 этого предложения (P0428R0), в котором предлагается добавить шаблонные лямбды в C++, gcc получил экспериментальную реализацию вышеупомянутой статьи в 2009 году. Это, вероятно, объясняет, почему gcc здесь не жалуется.

Ответ 2

Кажется, что это расширение GCC (шаблонные lambdas).

#include <iostream>

int main() {
    auto l = []<typename T>(T const& x){ std::cout << __PRETTY_FUNCTION__ << " " << x << std::endl;};
    l(42);
    l("Hello world");
}

приводит к

main()::<lambda(const T&)> [with T = int] 42
main()::<lambda(const T&)> [with T = char [12]] Hello world

Ответ 3

Данный код правильно сформирован и работает, как задумано, начиная с С++ 20.

За [expr.prim.lambda]:

лямбда-выражение:
лямбда-вводчик лямбда-декларатор opt составное-утверждение
лямбда-вводчик < шаблон-списка параметров > требует-условие опт лямбда-декларатор опт составной-оператор

Последняя строка отражает этот синтаксис.