This question also applies to boost::function
and std::tr1::function
.
std::function
is not equality comparable:
#include <functional>
void foo() { }
int main() {
std::function<void()> f(foo), g(foo);
bool are_equal(f == g); // Error: f and g are not equality comparable
}
The operator==
and operator!=
overloads are declared as deleted in C++0x with the comment (N3092 §20.8.14.2):
// deleted overloads close possible hole in the type system
It does not say what the "possible hole in the type system" is. In TR1 and Boost, the overloads are declared but not defined. The TR1 specification comments (N1836 §3.7.2.6):
These member functions shall be left undefined.
[Note: the boolean-like conversion opens a loophole whereby two function instances can be compared via
==
or!=
. These undefinedvoid
operators close the loophole and ensure a compile-time error. —end note]
My understanding of the "loophole" is that if we have a bool
conversion function, that conversion may be used in equality comparisons (and in other circumstances):
struct S {
operator bool() { return false; }
};
int main() {
S a, b;
bool are_equal(a == b); // Uses operator bool on a and b! Oh no!
}
I was under the impression that the safe-bool idiom in C++03 and the use of an explicit conversion function in C++0x was used to avoid this "loophole." Boost and TR1 both use the safe-bool idiom in function
and C++0x makes the bool
conversion function explicit.
As an example of a class that has both, std::shared_ptr
both has an explicit bool
conversion function and is equality comparable.
Why is std::function
not equality comparable? What is the "possible hole in the type system?" How is it different from std::shared_ptr
?