2011-12-12 27 views
8

Nói rằng tôi có một số loại loại gói lên một chức năng, có thể một hàm lambda:Điều gì xảy ra khi một loại có chứa lambda được gán?

template<typename Function> 
    struct my_struct 
{ 
    Function f; 

    my_struct(const Function &f) : f(f) {} 
}; 

gì xảy ra khi một thể hiện của loại hình này được gán? Sự hiểu biết của tôi là lambdas không thay đổi và đã xóa các toán tử gán.

Tuy nhiên, khi tôi gán cho một đối tượng kiểu này trong đoạn mã dưới đây, không có lỗi được phát ra:

// a structure which contains a function; 
// possibly a lambda function 
template<typename Function> 
    struct my_struct 
{ 
    Function f; 

    my_struct(const Function &f) : f(f) {} 

    // XXX adding this assignment operator causes an error 
    //my_struct &operator=(const my_struct &other) 
    //{ 
    // f = other.f; 
    // return *this; 
    //} 
}; 

template<typename Function> 
my_struct<Function> make_struct(const Function &f) 
{ 
    return my_struct<Function>(f); 
} 

int main() 
{ 
    // create some lambda 
    auto lambda = [](int x){return x;}; 

    // make a struct containing a copy of the lambda 
    auto x = make_struct(lambda); 

    // try to assign to the struct, which 
    // presumably assigns to the enclosed lambda 
    x = make_struct(lambda); 

    return 0; 
} 

Thêm toán tử gán nhận xét-out mang lại một lỗi, như mong đợi:

$ g++-4.6 -std=c++0x test.cpp 
test.cpp: In member function ‘my_struct<Function>& my_struct<Function>::operator=(const my_struct<Function>&) [with Function = main()::<lambda(int)>, my_struct<Function> = my_struct<main()::<lambda(int)> >]’: 
test.cpp:34:25: instantiated from here 
test.cpp:13:5: error: use of deleted function ‘main()::<lambda(int)>& main()::<lambda(int)>::operator=(const main()::<lambda(int)>&)’ 
test.cpp:27:18: error: a lambda closure type has a deleted copy assignment operator 

Vì vậy, có thể tạo các loại có thể gán với các biến thành viên lambda không? Điều này có vẻ giống như một điều hợp lý để thử. Hãy xem xét kết hợp một lambda với boost::transform_iterator, ví dụ.

+2

Tôi không biết nhiều về việc di chuyển, nhưng có thể chúng có thể được di chuyển nhưng không được sao chép không? Bạn có thể đã biết câu trả lời cho điều đó, nhưng tôi không hiểu biết về di chuyển-ctors vì vậy nếu bạn làm, xin vui lòng cho biết. –

+0

Cảm ơn ý tưởng, nhưng việc giới thiệu toán tử di chuyển dường như không thay đổi thông báo lỗi. –

Trả lời

12

Bạn thân thiết. Một lambda có một trình tạo bản sao ngầm và có thể có - tùy thuộc vào các giá trị đã capture - một hàm khởi tạo ngầm ẩn. Nó có một toán tử gán bản sao đã xóa.

Nói cách khác, bạn có thể xây dựng nó, nhưng bạn không thể gán nó. Nếu bạn đang tìm một đối tượng hàm chung, bạn muốn sử dụng std::function<>. Nó mô phỏng các hàm như là các giá trị hạng nhất.


Lưu ý rằng không thay đổi khác với chuyển nhượng được. Khi một lambda được gọi là có thể thay đổi, có nghĩa là cơ quan chức năng gọi của nó có thể thay đổi các thành viên của lambda (ví dụ, chức năng không phải là const):

int i = 0; 

auto okay = [=](int x) mutable { i += x; }; 
auto error = [=](int x) { i += x; }; 

Mỗi trong số này là sao chép constructable và không thể chuyển nhượng.

+3

Cảm ơn bạn đã giải thích. Phân công quá xấu sẽ bị xóa - dường như làm cho lambda không tương thích với '' 'boost :: transform_iterator''', ít nhất là với việc thực thi hiện tại của nó. –

+0

Xem [câu trả lời này] (http://stackoverflow.com/a/35412456/554283) để biết cách giải quyết khác (sử dụng std :: ref, thư viện Boost Fit được đề xuất và thư viện Tiện ích mở rộng phạm vi được đề xuất). –

+0

nhưng làm thế nào sau đó có thể std :: chức năng tạo một bản sao của lambda? –

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