2013-06-28 27 views
5

Tôi muốn chụp một 'tham khảo' để một lambda, và tôi nghĩ rằng một con trỏ hàm sẽ làm các trick, như trong:Làm cách nào để tạo 'tham chiếu' cho lambda?

int (*factorial)(int) = [&](int x){ 
    return (x < 2) 
     ? 1 
     : x * factorial(x - 1); 
}; 

nhưng tôi nhận cannot convert from main::lambda<......> to int(_cdecl *)(int).

Cách thích hợp để trỏ đến một lambda sau đó là gì?

+3

Một lambda có thể được chuyển đổi thành một con trỏ hàm nếu nó không nắm bắt bất cứ điều gì. – jrok

+0

Tuyệt, bạn nói đúng. Tốt để biết, cảm ơn. – sircodesalot

+0

Đây gần như là một bản sao của http://stackoverflow.com/questions/2067988/recursive-lambda-functions-in-c0x – doctorlove

Trả lời

6

Kể từ khi lambda không phải là không quốc tịch, nó không thể được chuyển đổi thành một con trỏ hàm. Sử dụng std::function để thay thế.

std::function<int(int)> factorial = [&](int x){ 
    return (x < 2) 
     ? 1 
     : x * factorial(x - 1); 
}; 
+1

Điều này có chi phí không đáng kể, như một cảnh báo, so với lambdas "thô". Mỗi cuộc gọi tương đương với phương thức 'ảo'. Nó không phải là xấu, nhưng so với công việc đang được thực hiện trong cuộc gọi, là đáng kể. – Yakk

+0

@Yakk Có, bạn phải trả chi phí xóa 'std :: function'; Tôi chỉ tìm kiếm câu trả lời đó từ vài tuần trước để liên kết với :) – Praetorian

+0

Điều đó có nghĩa là 'không stateless'? Ngoài ra, @ Yakk chi phí trên không là gì? – sircodesalot

5

Đây sẽ là gần nhất với những gì bạn đã:

std::function<int (int)> factorial = [&](int x){ 
    return (x < 2) 
     ? 1 
     : x * factorial(x - 1); 
}; 

thông thường bạn cũng có thể sử dụng auto, nhưng trong trường hợp này nó không hoạt động vì chức năng là đệ quy.

+1

'tự động' không hoạt động, hãy xem câu hỏi được liên kết. –

+0

@JesseGood: điểm tốt - cảm ơn. –

5

Bạn đã có câu trả lời hay. Sau đây chỉ là một sự tò mò nhưng tôi sẽ không đề nghị bạn sử dụng nó.

Khi người khác trả lời, lambda factorial cố gắng chụp chính nó và do đó nó không phải là không trạng thái. Do đó, nó không thể chuyển đổi thành con trỏ hàm.

Lambdas không cần phải nắm bắt đối tượng toàn cầu hoặc static, vì vậy nếu bạn thực hiện factorial một biến toàn cầu hoặc static sau đó bạn không cần phải nắm bắt nó và làm việc này tốt (gcc 4.7.2)

#include <iostream> 

    typedef int (*function)(int); 

    int main() { 
     static function factorial = [](int x){ 
      return (x < 2) ? 1 : x * factorial(x - 1); 
     }; 
     std::cout << factorial(5) << '\n'; 
    } 

bạn cũng có thể tạo một nhà máy như thế này:

#include <iostream> 

    typedef int (*function)(int); 

    function make_factorial() { 
     static function factorial = [](int x){ 
      return (x < 2) ? 1 : x * factorial(x - 1); 
     }; 
     return factorial; 
    } 

    int main() { 
     auto factorial = make_factorial(); 
     std::cout << factorial(5) << '\n'; 
    } 

Nếu bạn muốn xáo trộn nhiều hơn :-) sau đó loại bỏ typedef:

// This is a function returning a pointer to a function taking an int and returning an int. 
    int (*(make_factorial)())(int) { 
     static int (*factorial)(int) = [](int x){ 
      return (x < 2) ? 1 : x * factorial(x - 1); 
     }; 
     return factorial; 
    } 
Các vấn đề liên quan