使用 `std::function` 调用非 void 函数
不久前,我使用 std::function
非常像这样:
std::function<void(int)> func = [](int i) -> int { return i; };
基本上,我这样做是因为我想在 std::function
中存储不同的函数对象,但我不想限制这些函数的返回类型。由于这似乎有效,所以我就这么做了。但我不相信它可以安全使用,而且我还没有找到任何有关它的文档。有谁知道这种用法是否合法?或者更一般地说,可以安全地分配给 std::function 的对象的规则是什么?
编辑
为了澄清起见,我关心的问题是 lambda 函数返回一个 int
,而 func
声明为返回类型 void
。我不确定这是否可以,特别是在调用 func()
后。
A while ago I used std::function
pretty much like this:
std::function<void(int)> func = [](int i) -> int { return i; };
Basically, I did this because I wanted to store different function objects in a std::function
, but I didn't want to restrict the return types of these functions. Since this seemed to work, I went with it. But I'm not convinced that it is safe to use, and I haven't been able to find any documentation on it. Does anyone know whether this usage is legitimate? Or more generally, what the rules are for the object which can safely be assigned to a std::function
?
Edit
For clarification, the issue I'm concerned with is that the lambda function returns an int
, while func
is declared with return type void
. I'm not sure if this is OK, especially once a call to func()
is made.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的代码有未定义的行为。它可能会或可能不会按您的预期工作。它具有未定义行为的原因是由于 20.8.11.2.1 [func.wrap.func.con]/p7:
要使
f
对于返回类型R
可调用,f
必须返回可隐式转换为std::function 返回类型的内容
(在您的情况下为void
)。并且int
不能隐式转换为void
。我希望您的代码适用于大多数实现。然而,在至少一个实现(libc++)上,它无法编译:
具有讽刺意味的是,这种行为的基本原理源于另一个问题。
另一个问题提出了
std::function
使用的问题。该问题的解决方案涉及让实现在编译时强制执行 Requires: 子句。相反,此问题的解决方案是禁止实施强制执行Requires:子句。Your code has undefined behavior. It may or may not work as you expect. The reason it has undefined behavior is because of 20.8.11.2.1 [func.wrap.func.con]/p7:
For
f
to be Callable for return typeR
,f
must return something implicitly convertible to the return type of thestd::function
(void
in your case). Andint
is not implicitly convertible tovoid
.I would expect your code to work on most implementations. However on at least one implementation (libc++), it fails to compile:
Ironically the rationale for this behavior stems from another SO question.
The other question presented a problem with
std::function
usage. The solution to that problem involved having the implementation enforce the Requires: clause at compile time. In contrast, the solution to this question's problem is forbidding the implementation from enforcing the Requires: clause.您的用例已根据标准明确定义。您正在从可调用对象构造一个
std::function
[1]§20.8.11.2.1/7:
那么你的 f 是可调用的吗?
§20.8.11.2/2 说:
INVOKE
的定义如下:§20.8.2
由于任何类型都可以隐式转换为正如下面的 litb 所指出的,不存在隐式转换转换为 void 所以这没有很好的定义。void
,因此您的代码应该可以使用符合标准的编译器。[1]:我认为 lambda 在这里算作一个可调用对象,尽管我没有这方面的参考。您的 lambda 也可以用作函数指针,因为它不捕获上下文
Your use case is well-defined according to the standard.You are constructing a
std::function
from a callable object[1]§20.8.11.2.1/7:
So is your f callable?
§20.8.11.2/2 says:
And the definition of
INVOKE
says:§20.8.2
And since any type can be implicitly converted toAs pointed out by litb below, there isn't an implicit conversion to void so this isn't well defined.void
, your code should be fine with a standards-conforming compiler.[1]: I think the lambda counts as a callable object here, although I don't have a reference for that. Your lambda could also be used as a function pointer as it captures no context
这看起来对于匿名函数来说可能没问题。
引用自 http://www.alorelang.org/release/0.5/doc/std_function .html (这不是来自 C++ 标准库,但看起来他们正在使用类似的东西绑定到 C++)
另一种可能实现的方法是将函数指针存储在 auto 中,如下所示:http://en。 wikipedia.org/wiki/Anonymous_function(C++ 部分)
This looks like it may be ok for anonymous functions.
Quote from http://www.alorelang.org/release/0.5/doc/std_function.html (this is not from the C++ standard library, however it looks like they are using something similar in there bindings down to C++)
Another way this could possibly be done is by storing the function pointer in auto as seen here: http://en.wikipedia.org/wiki/Anonymous_function (C++ section)