2010-10-21 42 views
10

Làm cách nào để so sánh hai hàm lambda trong C++ (Visual Studio 2010)?Toán tử C++ lambda ==

std::function<void()> lambda1 = []() {}; 
std::function<void()> lambda2 = []() {}; 
bool eq1 = (lambda1 == lambda1); 
bool eq2 = (lambda1 != lambda2); 

Tôi nhận được lỗi biên dịch cho rằng toán tử == không thể truy cập được.

EDIT: Tôi đang cố gắng so sánh các phiên bản chức năng. Vì vậy lambda1 == lambda1 nên trả về true, trong khi lambda1 == lambda2 sẽ trả về false.

+1

Bạn đang cố gắng so sánh kết quả đánh giá lambdas hay chính lambdas? –

+0

Bạn có ý nghĩa gì với ==? Bạn kiểm tra bằng gì?Và nếu bạn không bao giờ biết, làm thế nào có thể trình biên dịch biết một mình, và chọn một toán tử == mà sẽ làm những gì bạn không biết? –

+2

@Joshua: Anh ấy rõ ràng đang cố gắng so sánh bản thân lambdas. Đó là một điều hoàn toàn hợp lý để làm cho bất cứ ai đến từ một ngôn ngữ với đối tượng chức năng lớp đầu tiên "thích hợp", trong lambda hoặc bất kỳ ký pháp nào khác. Mặc dù những ngôn ngữ đó có thể hoặc có thể không đồng ý về việc 'labda1' và' lambda2' trong đoạn mã trên có bằng nhau hay không, vì vậy Stephane có thể đã chỉ ra lý do tại sao C++ 0x bỏ qua 'operator ==' cho lambdas. –

Trả lời

12

Bạn không thể so sánh std::function đối tượng vì std::function is not equality comparable. Loại đóng cửa của lambda cũng không phải là sự tương đương bình đẳng. Tuy nhiên, nếu lambda của bạn không chụp bất cứ thứ gì, bản thân lambda có thể được chuyển đổi thành con trỏ hàm, và con trỏ hàm là tương đương (tuy nhiên, theo hiểu biết của tôi, nó hoàn toàn không được chỉ định trong ví dụ này là are_1and2_equaltrue hoặc false):

void(*lambda1)() = []() { }; 
void(*lambda2)() = []() { }; 
bool are_1and1_equal = (lambda1 == lambda1); // will be true 
bool are_1and2_equal = (lambda1 == lambda2); // may be true? 

Visual C++ 2010 does not support this conversion. Chuyển đổi không được thêm vào C++ 0x cho đến khi ngay trước khi Visual C++ được phát hành.

-3

Câu trả lời đơn giản nhất: Tất cả các mẫu <> Toán tử của hàm class ==() s là riêng tư.

followup câu hỏi: Những nếu sau cậu mong đợi:
- so sánh địa chỉ của các chức năng
- so sánh hai đối tượng riêng biệt (kiểu std :: function < void()>
- so sánh hai chức năng trừu tượng

Chỉnh sửa (gần 5 năm sau):

Tôi thấy thật thú vị khi có các ý kiến ​​phản đối mà không có ý kiến. Nếu downdotes là vì C++ 11 thay đổi cấp truy cập cho std :: function :: operator ==() , sau đó tôi nói cử tri không hiểu cách thức hoạt động của thời gian. f downvotes là bởi vì người hỏi câu hỏi không làm rõ những gì anh ta tưởng tượng toán tử ==() sẽ so sánh, có lẽ cử tri sẽ thấy cuộc thảo luận nhiều giờ qua bình luận ngay dưới câu hỏi, trong đó OP trả lời chỉ trong các nhận xét câu trả lời của tôi.

+0

Thứ nhất: so sánh địa chỉ của hàm. –

+0

C++ 11 không thay đổi cấp truy cập cho 'std :: function :: ', vì 'std :: function' không tồn tại trong C++ 03. Ngoài ra, 'operator ==' * không phải là * private (trong bất kỳ phiên bản nào của chuẩn); nó * không phải là chức năng thành viên *. Và nó không so sánh các địa chỉ hàm; nó chỉ cho phép so sánh với 'nullptr'. –

+0

Sau đó, tôi phải có được tâm linh kể từ khi tôi tham chiếu nó khoảng 10 tháng trước khi C + + 11 được hoàn thành. Ngoài ra, nó là một tham chiếu đến TR1 (2007) và bạn đang xác nhận nội dung chỉnh sửa của tôi: bạn không hiểu cách thức hoạt động của thời gian. –

2

Bạn không thể so sánh chức năng, kết thúc.

Bạn có thể so sánh hầu hết các con trỏ với các chức năng bằng các ngôn ngữ có khái niệm đó (ví dụ, EQ làm trong Lisp. Và không thành công cho các hàm tương đương không chiếm cùng một vị trí trong bộ nhớ.)

+2

+1. Việc so sánh lambdas có thể hoạt động ở một số ngôn ngữ trên cơ sở băm nhỏ các cây phân tích cú pháp của chúng (hoặc hoàn thành cùng một "tình cờ" thông qua việc ghi nhớ và so sánh địa chỉ của chúng), nhưng có rất ít cơ sở toán học cho một phép toán như vậy. Xác định rằng hai chức năng tùy ý làm điều tương tự là không thể. Các hàm rỗng là một trường hợp rất đặc biệt. – Potatoswatter

+2

Có hai khái niệm bình đẳng cho các chức năng: bình đẳng về định nghĩa và bình đẳng của hành vi. Việc đầu tiên có thể được thực hiện bằng cách so sánh văn bản chương trình theo một nghĩa nào đó (so sánh địa chỉ thực hiện là một biến thể về điều này) nhưng thứ hai là không thể; so sánh đầy đủ có chủ ý là chính xác cùng một đầm lầy tính toán như là vấn đề dừng. –

+0

@Potatoswatter Nhưng trình biên dịch biết loại lambda và lambdas có các kiểu duy nhất, vì vậy nó có thể cung cấp 'toán tử ==' cho lambdas cùng loại - bởi vì chúng là * cùng lambda *. Bản thân toán tử sẽ trả về 'true' IFF cùng một giá trị (bitwise, có lẽ) được bắt bởi mỗi lambda. –

0

Điều này là không thể.

Proof phác thảo: nếu nó là có thể tính toán

f1 == f2 

thì nó cũng sẽ có thể để tính toán

f == infiniteLoop 

và giải quyết các vấn đề ngăn chặn.

+0

Tôi không biết nếu bạn nghiêm túc, nhưng điều này là vô nghĩa. Hai nguồn/nhị phân/tập lệnh/cơ quan chức năng/... có thể dễ dàng so sánh (nói trong IR được chuẩn hóa/tối ưu hóa của trình biên dịch), nhưng điều này không giải quyết được vấn đề dừng. Bạn có thể kiểm tra xem nguồn/hàm// đã cho có nhất quán hay không. –

+1

Trong khi tôi đồng ý rằng không thể xác định rằng hai chức năng có cùng chức năng * trong trường hợp chung *, bình đẳng yếu hơn, hai hàm có cùng mã (Bảng trạng thái Turing, nếu bạn muốn) đều bằng nhau. Một sự tương đương thậm chí yếu hơn (có thể để lại ví dụ của OP bất bình đẳng) sẽ là chúng so sánh bằng nhau nếu chúng là cùng một đối tượng hàm, mà về cơ bản giống như so sánh các con trỏ hàm. – SingleNegationElimination

+0

@Matteo Italia, @TokenMacGuy: OP không chỉ định loại bình đẳng mà anh ấy đang tìm kiếm, vì vậy tôi giả định bình đẳng gia hạn, có vẻ như là định nghĩa thông thường. Nếu OP muốn có định nghĩa * khác thường *, anh ta nên cung cấp một câu hỏi. –