mas*_*coj 6 c++ gcc visual-c++ c++11
今天我遇到了一个有趣的问题.我创建了一个lambda,它接受对struct的引用,并错误地将它设置为std :: function,它按值接收它的参数.
这是一个更简洁的版本:
#include <functional>
struct InputStruct
{
int i;
InputStruct(): i(1){}
};
void function_rcv(std::function<bool(InputStruct)> & func_ref)
{
InputStruct in;
func_ref(in);
}
int main()
{
std::function<bool(InputStruct)> my_func = [](InputStruct & in)->bool{return in.i==1;};
function_rcv(my_func);
}
Run Code Online (Sandbox Code Playgroud)
用godbolt检查显示这与MSVC成功编译,但对于Clang和GCC都失败了.
有趣的是,使用原语而不是结构会在所有三个编译器上编译失败.
这是MSVC编译器中的错误吗?
总结:它不是编译器错误.MSVC接受此代码是因为其默认的不符合行为,但它可以符合标准,与交换机一致.
首先,我需要澄清std::function一个方面:它接受一个函数(一般来说,Callable)哪个签名不是完美匹配,但参数可以转换.考虑:
using intFn = void (int);
void fn(short);
intFn *a = fn; // doesn't compile
std::function<intFn> b = fn; // compiles!
Run Code Online (Sandbox Code Playgroud)
这里,intFn函数类型有一个int参数,而函数fn有一个short参数.简单的函数指针a,不能设置为指向fn,因为参数的类型不同(intvs short).但是,std::function允许这样,所以b可以设置为指向fn.
在您的示例中,std::function具有InputStruct参数值,而lambda具有非常量左值参考InputStruct &.当std::function std::forward它的参数为s时,它变成一个xvalue,它不能绑定到lambda的左值引用参数.这就是标准符合编译器不接受此代码的原因.
为什么MSVC接受此代码?因为默认情况下它具有不符合的行为:它允许将类临时(和xvalues)绑定到非const左值引用.您可以使用/Zc:referenceBinding(或更旧的/Za选项)禁用此行为.如果您使用此开关,MSVC拒绝您的示例.