Разница в сигнатуре лямбда с / без захваченной переменной? - PullRequest
6 голосов
/ 27 августа 2011

Я сейчас играю с C ++ 11 и обнаружил следующую проблему с использованием лямбда-выражения в качестве обратного вызова для sqlite.При захвате векторной переменной внутри лямбды я получаю сообщение о том, что подписи не совпадают.Без использования этой переменной в лямбде ([] вместо [&ret] и без использования ret внутри) она работает нормально.

vector<SomeClass> ret;
char *err = nullptr;
int res = sqlite3_exec(db,
                       "some sql query, doesn't matter",
                       [&ret](void *unused, int argc, char **argv, char **columnName) -> int
                       {
                           ret.push_back(SomeClass());
                           return 0;
                       },
                       nullptr,
                       &err);

Это ошибка, которую я получаю:

cannot convert 'TestClass::testMethod()::<lambda(void*, int, char**, char**)>' to 'int (*)(void*, int, char**, char**)' for argument '3' to 'int sqlite3_exec(sqlite3*, const char*, int (*)(void*, int, char**, char**), void*, char**)'

Версия GCC - "gcc (XvidVideo.RU - GCC 4.6.1 i686-pc-mingw32) 4.6.1 20110625 (предварительная версия)" в Windows.

Почему это имеет значение?

Ответы [ 2 ]

6 голосов
/ 27 августа 2011

Только лямбда без захвата может быть преобразована в указатели для работы, и, основываясь на диагностике компилятора, ваш sqlite3_exec ожидает такой указатель, int (*)(void*, int, char**, char**).

Цитировать §5.1.2 [expr.prim.lambda] / 6

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

1 голос
/ 21 июля 2016

как насчет использования 1-го аргумента для обратного вызова?

vector<SomeClass> ret;
char *err = nullptr;
int res = sqlite3_exec(db,
                       "some sql query, doesn't matter",
                       [](void *ctx, int argc, char **argv, char **columnName) -> int
                       {
                           static_cast<vector<SomeClass>*>(ctx)->push_back(SomeClass());
                           return 0;
                       },
                       &ret,
                       &err);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...