2011-11-03 23 views
5

Tôi có một số mã có thể giảm đáng kể về độ phức tạp bằng cách sử dụng lambdas. Tuy nhiên tiếc là chúng tôi phải sử dụng một trình biên dịch không hỗ trợ đầy đủ C++ 11 và chúng tôi không thể dễ dàng chuyển đổi. Bây giờ câu hỏi là làm thế nào để giữ logic càng gần càng tốt với một biểu thức lambda với các tính năng không có sẵn (tức là std::function có sẵn, lambdas thì không).Làm thế nào để xử lý lambdas trong một trình biên dịch trước lambda

Giải pháp thông thường là để xác định các functor ở một nơi khác và sau đó sử dụng nó ở nơi thích hợp:

struct functor{ 
    functor(type & member) : m_member(member) {} 
    void operator()(...) {...} 
    type & m_member; 
}; 

void function() { 
    use_functor(functor(...)); 
} 

Tôi rất nhiều sử dụng để mô hình này, mặc dù tôi không thích nó rất nhiều. Lý do chính để không định nghĩa lớp thường là tôi functor sẽ được sử dụng trong một STL và các mẫu không thích cấu trúc nội tuyến được định nghĩa của một hàm. Tuy nhiên trong trường hợp của tôi, hàm use_functor() sẽ là một phương thức bình thường, vì vậy tôi có thể định nghĩa hàm functor bên trong chính hàm đó (mỗi hàm functor chỉ được sử dụng trong một hàm).

void function() { 
    struct functor{ 
     functor(type & member) : m_member(member) {} 
     void operator()(...) {...} 
     type & m_member; 
    }; 
    use_functor(functor(...)); 
} 

Điều này có vẻ hơi cải thiện nhưng vẫn đòi hỏi nhiều mã xấu hơn mà tôi muốn. Ví dụ tôi muốn loại bỏ tên của functor hoàn toàn. Tôi biết có thể tạo một cấu trúc ẩn danh, nếu tôi chỉ sử dụng một giá trị.

void function() { 
    struct{ 
     // functor(type member) : m_member(member) {} 
     void operator()(...) {...} 
     // type & m_member; 
    } callback ; 
    use_functor(callback); 
} 

Tuy nhiên, tại thời điểm này tôi không có đầu mối về cách cung cấp các thành viên dữ liệu cần thiết. Vì cấu trúc ẩn danh nên nó không có hàm tạo. Tôi có thể dễ dàng thiết lập các thành viên, bởi vì nó là công khai, nhưng một lần nữa điều này sẽ thêm một dòng mà tôi không thích.

Mục đích là để nó ở trạng thái ít nhất có thể cần phải thay đổi khi chúng tôi chuyển sang trình biên dịch có lambdas sạch sẽ cho phép loại bỏ hoàn toàn vấn đề này.

Bạn sẽ làm thế nào để thực hiện việc này?

+0

Như tôi đã phải tìm ra, một số GCC cũ thậm chí không xử lý chuyển đổi từ cấu trúc lồng trong hàm thành std :: function <> rất tốt và sẽ không thích bất kỳ giải pháp nào. Vì vậy, tôi buộc phải sử dụng tùy chọn một và tách logic. – LiKao

Trả lời

1

Liên quan đến initalisation của các biến thành viên của một ẩn danh struct mà không có một constructor bạn có thể làm:

void function() { 
    type the_thing; 
    struct { 
     void operator()(...) {...} 
     type & m_member; 
    } callback = {the_thing}; 
    use_functor(callback); 
} 

để thiết lập các tài liệu tham khảo type &m_member trong callback.

0

Mở rộng trên câu trả lời của awoodland:

#define MY_LAMBDA(name, memberType, memberValue, body) \ 
    struct {          \ 
     void operator()(...) body    \ 
     memberType & memberValue;     \ 
    } name = {memberValue} 

void function() { 
    type thing_to_capture; 

    MY_LAMBDA(callback, type, thing_to_capture 
    { 
     std::cout << thing_to_capture << std::endl; 
    }); 

    use_functor(callback); 
} 

Bạn có thể sử dụng bất cứ nơi nào MY_LAMBDA bạn có thể định nghĩa một struct. Thật không may, nếu không có macro VARD, bạn phải bao bọc tất cả các đối tượng đã chụp vào một đối tượng duy nhất và bạn phải chỉ định loại đối tượng đó trong "tuyên bố lambda"

Cũng lưu ý rằng tương đương bằng lambda sẽ là:

void function() { 
    type thing_to_capture; 

    auto callback = [&thing_to_capture]() 
    { 
     std::cout << thing_to_capture << std::endl; 
    }; 

    use_functor(callback); 
} 
+0

Để loại trừ cơ hội lỗi chính tả, bạn có thể thêm 'type thing_to_capture;' vào đầu macro (nếu bạn không gọi một lệnh rõ ràng hoặc sao chép-gán, như trong ví dụ này). – Richard

+1

'MY_LAMBDA' hữu ích như thế nào mà không có khả năng xác định định nghĩa' toán tử '()'? – ildjarn

+0

@ildjarn Điểm tốt ... Chỉnh sửa sắp tới. –

0

Bạn có thể thử tăng thư viện lambda hoặc boost::phoenix. Cả hai đều được thiết kế để thực hiện các hoạt động kiểu lambda mà không cần hỗ trợ lambda thực tế. Vì chúng dựa trên mẫu, các lỗi có thể khó gỡ lỗi khi một cái gì đó không hoạt động như mong đợi.

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