使用`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
定义
INVOKE (f, t1, t2, ..., tN)
如下:…在所有其他情况下处理成员函数/ var指针…f(t1, t2, ..., tN)
。将
INVOKE (f, t1, t2, ..., tN, R) as INVOKE (f, t1, t2, ..., tN)
隐式转换为R
因为任何types都可以隐式转换为 正如下面的litb所指出的那样,没有一个隐式转换为void,所以这个定义没有定义好。 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)