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

Я сейчас играю с 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 ответа

Решение

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

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

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

Как насчет использования 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);
Другие вопросы по тегам