今天遇到了一个有趣的问题,这是由我自己的错误引起的。我创建了一个lambda,它接受对结构的引用,并错误地将其设置为一个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);
}
使用哥德波特进行的检查表明,这在MSVC中编译成功,但Clang和GCC都失败了。
有趣的是,使用原语而不是struct在所有三个编译器上都会失败编译。
这是MSVC编译器中的错误吗?
发布于 2019-02-21 00:44:15
总之:它不是编译器的错误。MSVC接受此代码,因为它的默认不符合行为,但它可以成为标准-符合一个开关。
首先,我需要澄清std::function
的一个方面:它接受一个签名不是完全匹配的函数(通常是可调用的),但是可以转换参数。
using intFn = void (int);
void fn(short);
intFn *a = fn; // doesn't compile
std::function<intFn> b = fn; // compiles!
这里,intFn
是一个函数类型,它有一个int
参数,而函数fn
有一个short
参数。简单函数指针a
不能设置为指向fn
,因为参数的类型不同(int
与short
)。但是,std::function
允许这样做,因此可以将b
设置为指向fn
。
在您的示例中,std::function
有一个值InputStruct
参数,而lambda有一个非const值引用InputStruct &
。当std::function
std::forward
的参数变为xvalue时,它不能绑定到lambda的lvalue引用参数。这就是为什么标准一致性编译器不接受这段代码的原因。
为什么MSVC接受这段代码?因为默认情况下它具有不协调的行为:它允许绑定类临时类(和lvalue )到非const lvalue引用。您可以使用/Zc:referenceBinding
(或旧的/Za
选项)禁用此行为。如果使用此开关,MSVC将拒绝您的示例。
https://stackoverflow.com/questions/54794587
复制相似问题