为什么c++ 17中std::函数的operator()发生了变化?
Why does operator() change for std::function in C++17?
以下代码在c++ 14中被认为是非法的,但在c++ 17中是合法的:
#include <functional>
int main()
{
int x = 1729;
std::function<void (int&)> f(
[](int& r) { return ++r; });
f(x);
}
不要费心去测试它,你会得到不一致的结果,这会让你很难判断这是一个bug还是故意的行为。然而,比较两个草案(N4140和N4527,两者都可以在github.com/cplusplus/draft上找到),[function .wrap. function .inv]有一个显著的区别。第二款:
返回:如果R为空则无返回值,否则调用INVOKE (f, std::forward(args)…右).
上述内容已在两次草案之间删除。这意味着lambda的返回值现在被静默地丢弃了。这似乎是一个错误的功能。有人能解释一下原因吗?
标准中关于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
不能隐式转换为void
2。
所以缺陷被解决了。std::function<void(Args...)>
现在接受任何可以用Args...
调用的东西,并丢弃返回值,正如许多现有编译器实现的那样。我推测这是因为(A)语言设计者从来没有打算限制,或者(B)为std::function
提供一种丢弃返回值的方法是需要的。
std::function
有从不要求参数或返回值的精确匹配,只是兼容性。如果传入参数可以隐式地从签名参数转换为返回类型,并且返回类型可以隐式地转换为返回类型,那么它就很高兴了。
在许多直观的定义下,int(int&)
类型的函数与签名void(int&)
兼容,因为您可以在"void上下文中"运行它。
1基本上,任何使operator()
合法调用的东西都是不允许的。您可以创建它,可以销毁它,可以测试它(并且知道它是空的)。您不能给它一个函数,即使是与它的签名完全匹配的函数,也不能给它一个函数对象或lambda。可笑。
2要将void
隐式地转换为void
,则要求语句void x = blah;
有效,其中blah
为void类型的表达式;该语句无效,因为您不能创建类型为void
的变量。
- 我正在将一个 std::string 传递给一个 boost 函数,该函数对该类型进行常量引用,但该值发生了变化
- c++问题:给一个变量赋值后,另一个变量发生了变化
- libstdc++的make_shared布局在gcc 4.x和gcc 6.x之间是否发生了变化?
- 为什么我的 int 在 C++ 程序中间发生了变化?
- 共享指针和回调注册的结构.由于我之外的原因调用回调时,原始指针值发生了变化
- 这个树搜索功能让我发疯.它返回 NULL,但不知何故主函数中的值发生了变化
- 默认初始化的含义在C 11中发生了变化
- c_str()的寿命是否在g++4.8.4和g++5.3.1之间发生了变化
- C++11与C++98转换运算符的行为发生了变化
- printf中的优先级似乎发生了变化
- 更改字符集后,MFC 应用程序的视觉外观发生了变化
- 在矢量中推回后,数字发生了变化
- 为什么std::vector的构造函数接口在C++11中发生了变化
- 对象似乎正在删除自己,或者在构造函数之后内存发生了变化
- 在c++中,对象可以警告类它已经发生了变化吗?
- 为什么c++ 17中std::函数的operator()发生了变化?
- 如何在sqlite3中检查列的数量是否发生了变化
- 当我没有给变量赋新值时,为什么变量的值发生了变化?
- 为什么退出函数时节点值发生了变化
- 检测表单中任何小部件的状态是否发生了变化