tags:

views:

192

answers:

4

How do I compare two lambda functions in C++ (Visual Studio 2010)?

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

I get a compilation error claiming that operator == is inaccessible.

EDIT: I'm trying to compare the function instances. So lambda1 == lambda1 should return true, while lambda1 == lambda2 should return false.

+7  A: 

You can't compare std::function objects because std::function is not equality comparable. The closure type of the lambda is also not equality comparable.

However, if your lambda does not capture anything, the lambda itself can be converted to a function pointer, and function pointers are equality comparable (however, to the best of my knowledge it's entirely unspecified whether in this example are_1and2_equal is true or 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. The conversion wasn't added to C++0x until just before Visual C++ was released.

James McNellis
A: 

Simplest answer: All of template<> class function's operator==()s are private.

Followup question: Which if the following did you expect:
- compare address of functions
- compare two distinct objects (of type std::function<void ()>
- compare two abstract functions

Eric Towers
The first one: compare address of functions.
crimson13
+3  A: 

You cannot compare functions, end of.

You can at most compare pointers to functions in languages that have that concept (this is also what, for example, EQ does in Lisp. And it fails for equivalent functions that do not occupy the same place in memory.)

nowayjose
+1. Comparing lambdas might work in some languages on the basis of hashing their parse trees (or accomplishing the same "by accident" through memoization and comparing their addresses), but there's little mathematical basis for such an operation. Determining that two arbitrary functions do the same thing is impossible. Empty functions are a very special case.
Potatoswatter
There are two notions of equality for functions: equality of definition and equality of behavior. The first could be done by comparison of program text in some sense (comparison of implementation address is a variation on this) but the second is impossible; full intentional comparison is in exactly the same computational marsh as the Halting Problem.
Donal Fellows
+3  A: 

This is impossible.

Proof sketch: if it were possible to compute

f1 == f2

then it would also be possible to compute

f == infiniteLoop

and solve the Halting Problem.

Jörg W Mittag
I don't know if you're serious, but this is nonsense. Two sources/binaries/scripts/function bodies/... can be easily compared (say in the normalized/optimized IR of the compiler), but this does not solve the halting problem. You may at most check if the given source/function/... is equal to one that is known to halt.
Matteo Italia
While I'll agree that it's impossible to determine that two functions are the same function *in the general case*, a weaker equality, two functions having the same code (Turing State Table, if you like) are equal. An even weaker equivalence (which could leave the OP's example inequal) would be that they compare equal if they are the same function object, which is basically the same as comparing function pointers.
TokenMacGuy
@Matteo Italia, @TokenMacGuy: The OP doesn't specify what kind of equality he is looking for, so I am assuming extensional equality, which seems to be the usual definition. If the OP wants an *unusual* definition, he should probaby provide one.
Jörg W Mittag
@Jörg W Mittag: in your definition, are `for(;;);` and `for(unsigned int i=0;;i=(i+1)%20) cout<<i;` equal?
Matteo Italia
@TokenMacGuy: But if only the code has to be identical, then, in any language which supports closures, you can have two functions be equal, and yet return different values when you call them. Not very intuitive.
jalf
@jalf: the captured variables in the closure are a part of the function's code/body. You can either view it in terms of the captured variables must be equal for the function to be equal, or else the captured variables are implicit arguments, and only when *all* arguments are identical are the functions the same. To take it a step further, is `std::time()` equal to itself? after all, each time you call it you get a different answer!
TokenMacGuy
@TokenMacGuy: Captured variables aren't usually part of the functions *code*, which was what you originally said. As for `std::time`, that's a good question too, which just underlines what I said: defining equality for functions isn't straightforward. :)
jalf
TokenMacGuy