为什么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中, operator==
和operator!=
overload是不存在的。 在早期的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!
}
我的印象是C ++ 03中的safe-bool习惯用法和C ++ 11中显式转换函数的使用被用来避免这种“漏洞”。 Boost和TR1都在function
使用safe-bool惯用法,C ++ 11使bool
转换函数显式化。
作为具有两者的类的示例, std::shared_ptr
都具有显式的bool
转换函数并且可以相等。
为什么std::function
不平等? 什么是“类型系统中可能出现的漏洞?” 它与std::shared_ptr
有什么不同?
为什么std::function
不平等?
std::function
是任意可调用类型的包装器,所以为了实现等式比较,您必须要求所有可调用类型都是相等比较的,从而给实现函数对象的任何人造成负担。 即使那样,你也会得到一个狭义的平等概念,因为如果(例如)它们是通过以不同的顺序绑定参数来构造的,等价函数会比较不等。 我认为在一般情况下测试等同性是不可能的。
什么是“类型系统中可能出现的漏洞?”
我猜想这意味着删除操作符变得更加容易,并且确定使用它们永远不会提供有效的代码,而不是证明在以前未发现的角落案例中不可能发生不需要的隐式转换。
它与std::shared_ptr
有什么不同?
std::shared_ptr
具有定义良好的相等语义; 两个指针在当且仅当它们都是空的时候是相等的,或者都是非空的并指向同一个对象。
这在Boost.Function常见问题解答中有详细讨论。 :-)
我可能是错的,但我认为std::function
对象的平等不幸在通用意义上是不可解的。 例如:
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <cstdio>
void f() {
printf("hellon");
}
int main() {
boost::function<void()> f1 = f;
boost::function<void()> f2 = boost::bind(f);
f1();
f2();
}
f1
和f2
相等? 如果我添加任意数量的函数对象,它们以各种方式简单地相互包装,最终归结为f
...的调用仍然相等?
上一篇: Why is std::function not equality comparable?
下一篇: Why is the volatile qualifier used through out std::atomic?