大约的标准有一个荒谬的缺陷std::function<void(Args...)>。根据标准的措辞,没有(非平凡的)1使用std::function<void(Args...)>是合法的,因为没有任何东西可以“隐式转换为” void(甚至不是void)。
void foo() {} std::function<void()> f = foo;在 C++14 中是不合法的。哎呀。
一些编译器采用了std::function<void(Args...)>完全无用的糟糕措辞,并将逻辑仅应用于返回值不是 void的传入可调用对象。然后他们得出结论,传递返回的函数(或任何其他非类型)是int非法std::function<void(Args...)>的void。他们没有把它带到逻辑结束并禁止函数返回void(std::function对于完全匹配的签名,要求没有特殊情况:同样的逻辑适用。)
void其他编译器只是忽略了返回类型案例中的错误措辞。
缺陷基本上是调用表达式的返回类型必须隐式转换为std::function的签名的返回类型(有关更多详细信息,请参见上面的链接)。并且在标准下,void不能隐式转换为void2。
所以缺陷就解决了。 std::function<void(Args...)>现在接受任何可以用 调用的东西Args...,并丢弃返回值,就像许多现有的编译器实现的一样。我认为这是因为(A)语言设计者从来没有打算过限制,或者(B)需要一种std::function丢弃返回值的方法。
std::function从来不需要参数或返回值的精确匹配,只是兼容性。如果传入参数可以从签名参数隐式转换,并且返回类型可以隐式转换为返回类型,那就很高兴了。
int(int&)在许多直观的定义下,类型函数与签名兼容void(int&),因为您可以在“无效上下文”中运行它。
1operator()基本上,不允许任何合法的调用。你可以创建它,你可以销毁它,你可以测试它(并且知道它是空的)。你不能给它一个函数,即使是一个与它的签名完全匹配的函数,或者一个函数对象或 lambda。荒谬的。
2为了在标准下void隐式转换void,它要求声明void x = blah;,其中blah是一个void类型的表达式,是有效的;该语句无效,因为您无法创建 type 的变量void。