使用`std :: function <void(…)>`来调用非void函数

前一段时间我使用std::function非常像这样:

 std::function<void(int)> func = [](int i) -> int { return i; }; 

基本上,我这样做是因为我想在std::function存储不同的函数对象,但我不想限制这些函数的返回types。 既然这似乎有效,我就跟着去了。 但我不相信这是安全的使用,我一直没能find任何文件。 有谁知道这个用法是否合法? 或者更一般地说,可以安全地分配给std::function的对象的规则是什么?

编辑

澄清,我关心的问题是lambda函数返回一个int ,而func声明返回types为void 。 我不确定这是否行,尤其是一旦调用func()

你的代码有未定义的行为。 它可能会或可能不会按照您的预期工作。 它有未定义行为的原因是因为20.8.11.2.1 [func.wrap.func.con] / p7:

要求: F应该是CopyConstructible 。 对于参数typesArgTypes和返回typesR f应为Callable(20.8.11.2)。

对于返回typesR来说f是Callable的, f必须返回隐式地转换为std::function的返回types的东西(在你的情况下是void )。 而int不能隐式转换为void

我希望你的代码可以在大多数的实现上工作。 但是至less在一个实现( libc ++ )中,它无法编译:

 test.cpp:7:30: error: no viable conversion from 'int (int)' to 'std::function<void (int)>' std::function<void(int)> ff = f; ^ ~ 

具有讽刺意味的是,这种行为的理由源于另一个SO问题 。

另一个问题提出了std::function用法问题。 该问题的解决scheme涉及在编译时执行Requires:子句。 相反,这个问题的解决scheme是禁止执行Requires:子句。

你的用例是根据标准定义好的。

你正在构造一个std::function从一个可调用的对象[1]

§20.8.11.2.1/ 7:

 template<class F> function(F f); 

要求:F应该是CopyConstructible。 对于参数typesArgType和返回typesR,f应为Callable(20.8.11.2)

那么你可以调用吗?

§20.8.11.2/ 2说:

如果expression式INVOKE (f, declval<ArgTypes>()..., R)被视为未评估的操作数(第5章),则typesF的可调用对象f对于参数typesArgTypes是可调用的,并且返回typesR是(20.8.2)。

INVOKE的定义是INVOKE

§20.8.2

  1. 定义INVOKE (f, t1, t2, ..., tN)如下:…在所有其他情况下处理成员函数/ var指针… f(t1, t2, ..., tN)

  2. INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN)隐式转换为R

因为任何types都可以隐式转换为void ,所以你的代码应该符合标准的编译器。 正如下面的litb所指出的那样,没有一个隐式转换为void,所以这个定义没有定义好。

[1]:我认为lambda算作一个可调用的对象,虽然我没有这个参考。 您的lambda也可以用作函数指针,因为它不捕获上下文

这看起来可能是匿名函数。

http://www.alorelang.org/release/0.5/doc/std_function.html引用(这不是来自C ++标准库,但看起来他们正在使用类似的东西绑定到C ++)

函数对象只能使用函数定义,匿名函数expression式或使用点(。)运算符访问绑定方法来创build。

另一种可能的方法是将函数指针存储在auto中,如下所示: http : //en.wikipedia.org/wiki/Anonymous_function (C ++ section)