Разница в типе лямбды при использовании [] и [this] - PullRequest
3 голосов
/ 17 декабря 2011

У меня есть класс db_interface. И определил лямбда-тип:

typedef void (*db_interface_lambda)();

Когда я создаю лямбду в классе таким образом: [](){ /* do something */ }, он имеет хороший тип (db_interface_lambda), но когда я использую [this](){ /* do something */ }, компилятор начинает кричать на меня.

cannot convert ‘db_interface::db_interface(std::ifstream&)::<lambda()>’ to ‘std::map<std::basic_string<char>, void (*)()>::mapped_type {aka void (*)()}’ in assignment

Как решить эту проблему? Какой правильный тип?

Ответы [ 3 ]

8 голосов
/ 17 декабря 2011

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

§5.1.2 [expr.prim.lambda] p6

Тип закрытия для лямбда-выражение без лямбда-захват ([] пусто) имеет открытую не виртуальную неявную функцию преобразования констант в указатель на функцию, имеющую тот же параметр, и возвращаеттипы как оператор вызова функции типа замыкания.

Кстати, что бы вы typedef не указывали на функцию, а на лямбда-тип.Лямбда-выражения имеют уникальный, безымянный, не объединенный тип класса .Вы не можете назвать их.

§5.1.2 [expr.prim.lambda] p3

Тип лямбда-выражения (который также является типом объекта замыкания) являетсяуникальный, неназванный тип класса nonunion

7 голосов
/ 17 декабря 2011

Вы пытаетесь вызвать что-то, что хочет указатель на функцию.Лямбда без захвата может быть автоматически преобразована в указатель на функцию, но как только вы пишете [this], она перестает быть без захвата - вы захватываете this, поэтому это ошибка.

Решение состоит в том, чтобы изменитьвведите std::function, а не указатель на функцию.std::function стирает тип «функтора», который он «оборачивает», так что вы все равно можете передать указатель на функцию, а также лямбу с захватом.

6 голосов
/ 17 декабря 2011

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

Лямбды, которые do перехватывают, по сути являются полными классами, и их нельзя просто преобразовать в указатель свободной функции. (Захватывающая лямбда - это, по сути, тот же класс функторов предикатов, который вы написали бы в C ++ до того, как у нас были лямбды.)

Любая версия лямбды может быть преобразована в std::function<void()>, что и должно быть отображенным типом вашей карты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...