2012-07-10 23 views
6

Xét đoạn mã sau:Chụp Lambda gây ra lỗi loại toán hạng không tương thích?

main() 
{ 
    bool t; 
    ... 
    std::function<bool (bool)> f = t ? [](bool b) { return b; } : [](bool b) { return !b; }; // OK 
    std::function<bool (bool)> f = t ? [t](bool b) { return t == b; } : [t](bool b) { return t != b; }; // error 
} 

Khi biên soạn với Clang 3.1, việc chuyển nhượng không chụp lambda hoạt động trong khi một với ảnh chụp không:

main.cpp:12:36: error: incompatible operand types ('<lambda at main.cpp:12:38>' and '<lambda at main.cpp:12:71>') 
     std::function<bool (bool)> f2 = t ? [t](bool b) { return t == b; } : [t](bool b) { return t != b; }; // error 
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Tại sao chụp cùng một biến gây ra 2 lambdas là loại không tương thích?

Trả lời

12

Loại lambda là "loại lớp duy nhất, phi công đoàn" được gọi là loại đóng. Mỗi lambda được thực hiện dưới dạng một kiểu khác nhau, cục bộ với phạm vi khai báo, có một toán tử quá tải() để gọi cho thân hàm.

Ví dụ: nếu bạn viết này:

auto a=[t](bool b){return t==b;}; 
auto b=[t](bool b){return t!=b;}; 

Sau đó trình biên dịch biên dịch này (nhiều hơn hoặc ít hơn):

class unique_lambda_name_1 
{ 
bool t; 
public: 
unique_lambda_name_1(bool t_) t(_t) {} 
bool operator() (bool b) const { return t==b; } 
} a(t); 
class unique_lambda_name_2 
{ 
bool t; 
public: 
unique_lambda_name_2(bool t_) t(_t) {} 
bool operator() (bool b) const { return t!=b; } 
} b(t); 

a và b có các loại khác nhau và không thể được sử dụng trong toán tử?:

Tuy nhiên, §5.1.2 (6) nói rằng kiểu đóng của lambda không có bắt giữ có toán tử chuyển đổi công khai không rõ ràng, chuyển đổi lambda thành con trỏ hàm - không thể đóng được như các hàm đơn giản. Bất kỳ lambda nào có cùng tham số và kiểu trả về có thể được chuyển đổi thành cùng một kiểu con trỏ và do đó toán tử ternary ?: có thể được áp dụng cho chúng.

Ví dụ: phi chụp lambda:

auto c=[](bool b){return b;}; 

được thực hiện như thế này:

class unique_lambda_name_3 
{ 
static bool body(bool b) { return b; } 
public: 
bool operator() (bool b) const { return body(b); } 
operator decltype(&body)() const { return &body; } 
} c; 

điều đó có nghĩa rằng dòng này:

auto x = t?[](bool b){return b;}:[](bool b){return !b;}; 

nghĩa thực sự này:

// a typedef to make this more readable 
typedef bool (*pfun_t)(bool); 
pfun_t x = t?((pfun_t)[](bool b){return b;}):(pfun_t)([](bool b){return !b;}); 
+0

Cảm ơn bạn đã giải thích chi tiết. Tôi không biết chúng được thực hiện khác nhau. Nó có ý nghĩa bây giờ. –

Các vấn đề liên quan