Этот вопрос также относится к boost::function
и std::tr1::function
.
std::function
не эквивалентно равенству:
#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
}
В С++ 11 перегрузки operator==
и operator!=
просто не существуют. В раннем проекте С++ 11 перегрузки были объявлены как удаленные с комментарием (N3092 §20.8.14.2):
// deleted overloads close possible hole in the type system
Он не говорит, что такое "возможное отверстие в системе типов". В TR1 и Boost перегрузки объявлены, но не определены. Спецификация спецификации TR1 (N1836 §3.7.2.6):
Эти функции-члены должны быть оставлены undefined.
[Примечание: логическое преобразование открывает лазейку, посредством которой два экземпляра функции можно сравнить с помощью
==
или!=
. Эти операторы undefinedvoid
закрывают лазейку и обеспечивают ошибку времени компиляции. -end note]
Мое понимание "лазейки" состоит в том, что если у нас есть функция преобразования bool
, это преобразование может использоваться при сравнении сравнений (и в других обстоятельствах):
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!
}
У меня создалось впечатление, что идиома safe-bool в С++ 03 и использование явной функции преобразования в С++ 11 использовались, чтобы избежать этой "лазейки". Boost и TR1 используют идиому safe-bool в function
, а С++ 11 делает функцию преобразования bool
явной.
В качестве примера класса, который имеет оба параметра, std::shared_ptr
имеет явную функцию преобразования bool
и сопоставим равенство.
Почему std::function
не сопоставимо равенство? Какая "возможная дыра в системе типов"? Чем он отличается от std::shared_ptr
?