Почему std :: function не сравнимо по равенству

Этот вопрос также относится к 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
}

В C ++ 11 оператор == и оператор ! = перегрузок просто не существует. В ранней версии C ++ 11 перегрузки были объявлены как удаленные с комментарием (N3092 §20.8.14.2):

// deleted overloads close possible hole in the type system

В нем не говорится, что такое «возможная дыра в системе типов». В TR1 и Boost перегрузки объявляются, но не определяются. Комментарии спецификации TR1 (N1836 §3.7.2.6):

Эти функции-члены должны быть оставлены неопределенными.

[ Примечание: булево-подобное преобразование открывает лазейку, в которой можно сравнить два экземпляра функции через == или ! = . Эти неопределенные операторы void закрывают лазейку и обеспечивают ошибку времени компиляции. - конец заметки ]

Мое понимание "лазейки" заключается в том, что если у нас есть функция преобразования 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 в C ++ 03 и использование явной функции преобразования в C ++ 11 использовались, чтобы избежать этой «лазейки». Boost и TR1 используют идиому safe-bool в функции , а C ++ 11 делает функцию преобразования bool явной.

В качестве примера класса, который имеет оба, std :: shared_ptr оба имеют явную функцию преобразования bool и сопоставимы по равенству.

Почему std :: функция не сравнима ли равенство? Что такое «возможная дыра в системе типов»? Чем он отличается от std :: shared_ptr ?

61
задан Xeo 27 October 2012 в 23:37
поделиться