2011-08-26 26 views
6

Tôi đang chơi xung quanh với C++ 11 ngay bây giờ và tìm thấy vấn đề sau với việc sử dụng một lambda như gọi lại để sqlite. Khi chụp một biến vector bên trong lambda, tôi nhận được một lỗi nói rằng các chữ ký không khớp. Không sử dụng biến đó trong lambda ([] thay vì [&ret] và không sử dụng ret bên trong), nó hoạt động tốt.Sự khác biệt chữ ký giữa lambda có/không có biến bị bắt?

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); 

Đây là lỗi tôi nhận được:

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**)' 

phiên bản GCC là "gcc (XvidVideo.RU - GCC 4.6.1 i686-pc-mingw32) 4.6.1 20.110.625 (phát hành trước)" trên Các cửa sổ.

Tại sao điều này tạo sự khác biệt?

+0

Tôi đang cố gắng điều tương tự với trình biên dịch trực quan 2010 và không giống như hình thức lambda ... Có ai biết nếu đây là lỗi đã biết trong cấy VS2010 không? –

Trả lời

6

Chỉ lambdas vô nghĩa có thể được chuyển đổi thành con trỏ để hoạt động, và, dựa trên chẩn đoán trình biên dịch, sqlite3_exec của bạn mong đợi con trỏ như vậy, int (*)(void*, int, char**, char**).

Để báo §5.1.2 [expr.prim.lambda]/6

Kiểu đóng cửa cho một lambda thể hiện không có lambda-chụp có chức năng chuyển đổi const không ảo không rõ ràng công cộng để trỏ tới hàm có cùng tham số và kiểu trả về như toán tử gọi hàm của kiểu đóng.

+0

Làm cho tinh thần. Chỉ muốn biết nếu tôi có thể giải quyết điều này với các biến bị bắt theo bất kỳ cách nào. (Trong trường hợp đặc biệt này, tất nhiên tôi có thể sử dụng biến gọi lại của sqlite cho mục đích của mình.) – AndiDog

+0

@AndiDog Tôi đoán bạn phải đi theo cách gọi rất nhiều C++ cho thư viện C: một thành viên không phải là thành viên hoặc thành viên tĩnh tìm ra những gì thực sự gọi dựa trên một số 'void *'. – Cubbi

+2

Có, 'sqlite3_exec' cho phép tôi chuyển một' void * 'vào cuộc gọi lại, tôi chỉ ngây thơ nghĩ rằng điều này có thể được thực hiện dễ dàng hơn với C++ 11. – AndiDog

1

điều gì về việc sử dụng đối số thứ nhất để gọi lại?

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); 
Các vấn đề liên quan