代码之家  ›  专栏  ›  技术社区  ›  lubgr

在调用之前,为什么或何时应将可调用函数参数强制转换为rvalue?

  •  3
  • lubgr  · 技术社区  · 6 年前

    到目前为止,我已经考虑过传递和调用一个callable作为

    template <class Fct, class... Args> void f(Fct&& g, Args&&... args)
    {
        g(std::forward<Args>(args)...);
    }
    

    是一条路。现在在 this talk (34分钟)和 std::invoke 示例实现中,我看到了上述代码片段的等价性,它在调用rvalue引用之前有条件地将callable强制转换为rvalue引用,

    template <class Fct, class... Args> void f(Fct&& g, Args&&... args)
    {
        std::forward<Fct>(g)(std::forward<Args>(args)...);
    }
    

    我假设这个修改只影响闭包,但我仍然不明白为什么第二个版本更可取:强制转换只影响rvalue参数,调用时不应复制任何状态,对吗?我还检查了 std::function::operator() 已超载 & && 通过上述代码片段之外的库获取提示,但事实并非如此。

    提前谢谢你的提示和回答!

    1 回复  |  直到 6 年前
        1
  •  6
  •   llllllllll    6 年前

    完美转发的关键是尽可能地保留原始信息。

    g(std::forward<Args>(args)...); 将删除原始函数对象的rvalue/lvalue信息, g 总是 被视为左值。

    这将产生明显的影响,例如:

    struct foo {
        void operator()(int) & {
            std::cout << "& called\n";
        }
    
        void operator()(int) && {
            std::cout << "&& called\n";
        }
    };
    

    foo{}(1) 将调用第二个 operator() 是的。如果你使用第一种方法 std::forward 我是说, f(foo{}, 1) 将调用第一个 运算符() 是的。