2009-09-29 42 views
6

Tôi đã đọc một chút về biểu thức lambda trên internet gần đây và dường như với tôi rằng biểu thức lambda của C++ 0x sẽ không có một kiểu (hoặc kiểu) nào sẽ liên kết độc quyền với các biểu thức lambda - nói cách khác , biểu thức lambda sẽ chỉ khớp với đối số mẫu hoặc auto đối số/biến. Chuyện gì xảy ra, như mô tả here, làCó phải các biểu thức lambda của C++ 0x không có loại có tên không?

Trình biên dịch hỗ trợ lambdas sẽ tạo độc đáo ẩn danh functor loại cho mỗi biểu thức lambda

Câu hỏi của tôi là, đó là một điều xấu? Sẽ không có ý nghĩa khi có một số từ khóa chỉ phù hợp với các biểu thức lambda, ví dụ: lambda, mà sẽ làm việc như sau

void f(std::function<int(int)> func) 
{ 
    func(2); 
} 

template<typename T> 
void g(T func) 
{ 
    func(2); 
} 

void h(lambda func) 
{ 
    func(2); 
} 

int main() 
{ 
    int fpointer(int); 
    struct { int operator()(int var) { return var; } } functor; 

    f(fpointer); //ok (actually a linker error, but for the sake of example) 
    f(functor); //ok 
    f([](int var) { return var; }); //ok 

    g(fpointer); //ok 
    g(functor); //ok 
    g([](int var) { return var; }); //ok 

    h(fpointer); //error -- function pointer isn't a lambda expr 
    h(functor); //error -- functor isn't a lambda expr 
    h([](int var) { return var; }); //ok 

    return 0; 
} 

Thành thật mà nói, tôi thực sự không thể nhìn thấy tính hữu ích của việc này (đặc biệt là cho rằng auto chấp nhận biểu thức lambda, vì vậy người ta sau đó có thể gán một lambda cho một biến), nhưng nó vẫn không ngồi ngay với tôi rằng các biểu thức lambda là các kiểu ẩn danh và không thể bị ràng buộc cụ thể chỉ với một loại cụ thể (để loại trừ tất cả các loại khác). Về bản chất, câu hỏi của tôi là, có ổn không khi các biểu thức lambda ẩn danh (cả về mặt tiện ích - việc thiếu một kiểu lambda không cho chúng ta một số chức năng - và theo triết học - liệu nó có thực sự có ý nghĩa hay không rằng các biểu thức lambda luôn có 'loại' auto)?

+6

Có vẻ như bạn không biết rằng bạn có thể chấp nhận các biểu thức lambda bằng cách sử dụng 'std :: function ' quá. –

+0

Tôi đã, tuy nhiên kể từ khi chức năng chung phù hợp với cách 'tự động hoạt động (afaik), tôi nghĩ rằng nó không cần thiết để thêm * một bộ * chức năng ví dụ/chức năng cuộc gọi (nhưng nó vẫn còn tốt đề cập đến, vì vậy cảm ơn litb) – GRB

+2

tôi nghĩ có một sự hiểu lầm về tự động. không thể sử dụng tự động làm kiểu tham số trong hàm. Nó không phải là một loại. tự động chỉ nói "suy ra loại từ initializer vì tôi quá lười biếng hoặc chỉ không thể đặt tên cho loại". – sellibitze

Trả lời

11

Lambdas là các loại độc lập. Mã số

void h(lambda func) 
{ 
    func(2); 
} 

không có ý nghĩa gì vì lambdas không có đa hình thời gian chạy. Nhớ lại rằng một lambda là tương đương với

struct unique_name 
{ 
    return_type operator()(Arg1 a1, Arg2 a2, ... , Argn an) 
    { 
     code_inside_lambda; 
    } 
} 

Bản thân nó là một kiểu duy nhất. Mã ở trên sẽ giống như cách nói

void h(class C) 
{ 
    C(2); 
} 

Mà cũng không có ý nghĩa ngay cả khi chúng tôi đảm bảo rằng C có operator(). Bạn cần một mẫu:

template<typename T> 
void g(T func) 
{ 
    func(2); 
} 

int main() 
{ 
    g([](int x){return x + 2;}); 
} 
+0

Bạn thực hiện một điểm tốt về ý tưởng có 'void h (class C)', tuy nhiên tôi * có thể * làm 'void h (functor_name C)' sẽ chỉ khớp với các tham số của kiểu functor cụ thể đó. Tôi không thể làm như vậy với một biểu thức lambda. – GRB

+1

Nếu bạn cần tham khảo một lambda cụ thể theo tên, bạn nên xác định nó theo cách cũ bằng cách sử dụng một 'struct'. Một biểu thức lambda, theo định nghĩa, ẩn danh. – rlbond

+0

Đó là một điểm tốt, nếu bạn cần chuyên về các biểu thức lambda (mặc dù nó không cung cấp chức năng), bạn có thể sử dụng chúng không chính xác (và sẽ đi ngược lại lý thuyết về các giai đoạn lambda). Plus, như tôi đã đề cập và như mọi người khác đã đề cập, có lẽ chỉ có thể không có tiện ích cho nó (mặc dù litb của quyền mà ai đó sẽ thêm một phần mở rộng trình biên dịch không chuẩn cho nó anyway). Tôi đã chấp nhận câu trả lời này – GRB

3

Tôi không thấy lý do nào để phân biệt các loại chức năng dựa trên việc chức năng có tên hay không. Hàm lambda chỉ là một cách viết tắt, cho phép bạn định nghĩa một hàm tiện lợi một cách dễ dàng. Tên hoặc không có tên, hành vi của hàm khi được gọi là giống nhau.

Hãy suy nghĩ theo cách này. Phiên bản đầu tiên của phần mềm của bạn có một biến vị ngữ được định nghĩa là một hàm ẩn danh. Theo thời gian, các yêu cầu trở nên phức tạp hơn và vị từ của bạn cũng phức tạp hơn - và có thể bạn cần phải gọi nó từ nhiều nơi. Điều hợp lý để làm là để tái cấu trúc để bạn có một chức năng được đặt tên.

Không có lý do tại sao hàm được gọi (hàm gọi là biến vị ngữ) nên quan tâm đến điều đó. Đơn giản hoặc phức tạp, có tên hoặc ẩn danh - nó vẫn chỉ là một hàm vị ngữ.

Một vấn đề nhỏ là đóng cửa - tôi chưa kiểm tra, nhưng với một chút may mắn, C++ sẽ nhận được các hàm được đặt tên lồng nhau có đóng cũng như lambdas.

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