【问题标题】:Why does this incorrect std::function initialization compile using MSVC?为什么这个不正确的 std::function 初始化使用 MSVC 编译?
【发布时间】:2019-07-14 15:06:42
【问题描述】:

今天遇到了一个有趣的问题,由我自己的错字开始。我创建了一个 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);
}

检查godbolt 表明这使用 MSVC 成功编译,但对于 Clang 和 GCC 都失败。

有趣的是,在所有三个编译器上使用原语而不是结构都会导致编译失败。

这是 MSVC 编译器中的错误吗?

【问题讨论】:

  • 在我看来是个错误。
  • @NathanOliver 有趣的东西。如果有机会,我必须向 Microsoft 提交错误。
  • 这只是通常的“MSVC 允许临时绑定到左值引用”。用/Zc:referenceBinding编译不会编译。
  • @SergeyA 我相信关于构造函数 5 的注释是有原因的(此构造函数不参与重载决议,除非 f 对于参数类型 Args... 和返回类型 R 是可调用的。)。 std::function&lt;bool(InputStruct)&gt; 可以采用右值,但 [](InputStruct &amp; in)-&gt;bool 不能,所以它应该会失败。
  • @SergeyA 如果它们是左值,那当然。问题是std::functionoperator() 将为底层函数对象调用INVOKE&lt;R&gt;(f, std::forward&lt;Args&gt;(args)...),如果将右值传递给operator(),那么底层函数对象将获得一个右值,它不能绑定到左值引用。

标签: c++ c++11 gcc visual-c++


【解决方案1】:

总而言之:这不是编译器错误。 MSVC 接受此代码是因为其默认的不符合行为,但可以通过开关使其符合标准。

首先需要澄清std::function的一个方面:它接受一个函数(一般来说,Callable),它的签名不是完全匹配,但是参数可以转换.考虑:

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 vs short)。但是,std::function 允许这样做,因此可以将b 设置为指向fn

在您的示例中,std::function 有一个 InputStruct 参数值,而 lambda 有一个非常量左值引用 InputStruct &amp;。当std::functionstd::forwards它的参数时,它变成了一个xvalue,它不能绑定到lambda的左值引用参数。这就是符合标准的编译器不接受此代码的原因。

为什么 MSVC 接受此代码?因为默认情况下它具有不一致的行为:它允许将类临时(和 xvalues)绑定到非 const 左值引用。您可以使用/Zc:referenceBinding(或旧的/Za 选项)禁用此行为。如果您使用此开关,MSVC 会拒绝您的示例。

【讨论】:

  • 说得好。感谢您提供完整的细分。
猜你喜欢
  • 1970-01-01
  • 2015-05-13
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多