鉴于以下代码,模糊性背后的原因是什么?我可以绕过它还是我必须保持(讨厌的)显式演员?
#include <functional>
using namespace std;
int a(const function<int ()>& f)
{
return f();
}
int a(const function<int (int)>& f)
{
return f(0);
}
int x() { return 22; }
int y(int) { return 44; }
int main()
{
a(x); // Call is ambiguous.
a(y); // Call is ambiguous.
a((function<int ()>)x); // Works.
a((function<int (int)>)y); // Works.
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,如果我a()用function<int ()>参数注释掉函数并a(x)在我的main中调用,则编译正确失败,因为它们之间的类型不匹配x和function<int (int)>唯一a()可用函数的参数.如果编译器在这种情况下失败,为什么在存在这两个a()函数时会有任何歧义?
我试过VS2010和g ++ v.4.5.两者都给我完全相同的歧义.
所有报价均来自N3797.
4/3 [转]
当且仅当声明T t = e时,表达式e可以隐式转换为类型T. 对于一些发明的临时变量t而言,其形式良好
这意味着没有表达式可以隐式转换为void,这void t=e对所有表达式都是非法的e.如果e是类型的表达式void,例如,这甚至是真的void(3).
所以类型的表达式void不能隐式转换为void.
这导致我们:
20.9.2/2要求[func.require]
将INVOKE(f,t1,t2,...,tN,R)定义为隐式转换为R的INVOKE(f,t1,t2,...,tN).
总之,INVOKE(f, t1, t2, ..., tN, R)当是永远有效R的void,如无(含void)可以隐式转换为void.
因此,所有都std::function<void(Args...)>具有属性!*this,因此不能被调用,因为唯一没有!*this后置条件的构造函数(或者不从function相同类型的另一个复制此类状态)需要Callable其中一个参数.
20.9.11.2/7类模板函数[func.wrap.func]
要求:F应为CopyConstructible.对于参数类型ArgTypes,f应为Callable(20.9.11.2)并返回R类型.A的拷贝构造函数和析构函数不应抛出异常.
20.9.11.2/2类模板函数[func.wrap.func]
类型F的可调用对象f对于参数类型ArgTypes是Callable,如果表达式INVOKE(f,declval()...,R)被认为是未评估的操作数(第5条),则返回类型R( 20.9.2).
如上所述,没有Callable表达std::function<void(Args...)>.
如果以某种方式std::function<void(Args...)>找到这样的地方,调用operator()将会形成错误:
调用[func.wrap.func.inv]
效果:INVOKE(f,std :: forward(args)...,R)(20.9.2),其中f是*this的目标对象(20.9.1).
因为INVOKE(f, …
前一段时间我用std::function的很像:
std::function<void(int)> func = [](int i) -> int { return i; };
Run Code Online (Sandbox Code Playgroud)
基本上,我这样做是因为我想在a中存储不同的函数对象std::function,但我不想限制这些函数的返回类型.由于这似乎有效,我接受了它.但我不相信它是安全的,我也无法找到任何文件.有谁知道这种用法是否合法?或者更一般地说,对象的规则是什么,可以安全地分配给std::function?
为了澄清,我关心的问题是lambda函数返回一个int,而func声明返回类型void.我不确定这是否正常,特别是一旦打电话func().