История изменений
Исправление rumgot, (текущая версия) :
А неявные преобразования зло
Нет. Неявные неожиданные преобразования зло. А ожидаемые и желаемые - нет.
Неправильно ты ответил. Лямбда это всегда функтор. В твоём случае происходит неявное преобразование
Да. Признаю. Перечитал стандарт.
Просто когда нет захвата, он реализует метод как статический метод класса
А вот тут ты наврал.
C++17 Draft N4659 8.1.5.1 Closure types
The closure type for a non-generic lambda-expression with no lambda-capture has a conversion function to
pointer to function with C ++ language linkage (10.5) having the same parameter and return types as the
closure type’s function call operator.
Итого исправленный комментарий:
#include <functional>
#include <iostream>
using namespace std;
class Functor {
public:
Functor(){};
void operator()() { cout << "Functor::operator()" << endl; }
};
void caller(void (*fp)()) { fp(); }
template <typename F>
void callerTemplate(F f) {
f();
}
int main() {
// Здесь можно присвоить лямбда-выражение указателю на функцию (или передать в качестве указателя
// на функцию в другую функцию) потому что лямбда без списка захвата (в этом случае лямбда реализована
// компилятором как функтор у которого есть функция преобразования в указатель на функцию с такой же сигнатурой вызова, что и
// оператор вызова operator() данного функтора и поэтому данную лямбду можно привести к указателю на функцию):
void (*p0)() = []() { cout << "Lambda without capture list called" << endl; }; // Ok
caller([]() { cout << "Lambda without capture list called" << endl; }); // Ok
int i{};
// А в случае, когда лямбда имеет список захвата, компилятор реализует ее как функтор без функции
// преобразования в указатель на функцию (который уже нельзя привести к указателю на функцию):
// void (*p1)() = [i]() { cout << "Lambda with capture list called " << i << endl; }; // Ошибка компиляции
// caller([i]() { cout << "Lambda with capture list called " << i << endl; }); // Ошибка компиляции
// caller(Functor()); // Ошибка компиляции
// В случае использования шаблонов, один шаблон может принимать функциональные сущности разных типов
// (разумеется для каждого типа будет инстанцирован свой экземпляр шаблона):
callerTemplate([i]() { cout << "Lambda with capture list called " << i << endl; });
callerTemplate(Functor());
}
Исправление rumgot, :
А неявные преобразования зло
Нет. Неявные неожиданные преобразования зло. А ожидаемые и желаемые - нет.
Неправильно ты ответил. Лямбда это всегда функтор. В твоём случае происходит неявное преобразование
Да. Признаю. Перечитал стандарт.
C++17 Draft N4659 8.1.5.1 Closure types
The closure type for a non-generic lambda-expression with no lambda-capture has a conversion function to
pointer to function with C ++ language linkage (10.5) having the same parameter and return types as the
closure type’s function call operator.
Итого исправленный комментарий:
#include <functional>
#include <iostream>
using namespace std;
class Functor {
public:
Functor(){};
void operator()() { cout << "Functor::operator()" << endl; }
};
void caller(void (*fp)()) { fp(); }
template <typename F>
void callerTemplate(F f) {
f();
}
int main() {
// Здесь можно присвоить лямбда-выражение указателю на функцию (или передать в качестве указателя
// на функцию в другую функцию) потому что лямбда без списка захвата (в этом случае лямбда реализована
// компилятором как функтор у которого есть функция преобразования в указатель на функцию с такой же сигнатурой вызова, что и
// оператор вызова operator() данного функтора и поэтому данную лямбду можно привести к указателю на функцию):
void (*p0)() = []() { cout << "Lambda without capture list called" << endl; }; // Ok
caller([]() { cout << "Lambda without capture list called" << endl; }); // Ok
int i{};
// А в случае, когда лямбда имеет список захвата, компилятор реализует ее как функтор без функции
// преобразования в указатель на функцию (который уже нельзя привести к указателю на функцию):
// void (*p1)() = [i]() { cout << "Lambda with capture list called " << i << endl; }; // Ошибка компиляции
// caller([i]() { cout << "Lambda with capture list called " << i << endl; }); // Ошибка компиляции
// caller(Functor()); // Ошибка компиляции
// В случае использования шаблонов, один шаблон может принимать функциональные сущности разных типов
// (разумеется для каждого типа будет инстанцирован свой экземпляр шаблона):
callerTemplate([i]() { cout << "Lambda with capture list called " << i << endl; });
callerTemplate(Functor());
}
Исходная версия rumgot, :
А неявные преобразования зло
Нет. Неявные неожиданные преобразования зло. А ожидаемые и желаемые - нет.
Неправильно ты ответил. Лямбда это всегда функтор. В твоём случае происходит неявное преобразование
Да. Признаю. Перечитал стандарт.
C++17 Draft N4659 8.1.5.1 Closure types
The closure type for a non-generic lambda-expression with no lambda-capture has a conversion function to
pointer to function with C ++ language linkage (10.5) having the same parameter and return types as the
closure type’s function call operator.