std :: function是否支持完美转发?

时间:2018-04-01 20:50:41

标签: c++ templates

std::function是否支持完美转发参数?我决定测试一下:

struct Widget
{
    void operator()(int const&)
    {
        std::cout << "lvalue";
    }

    void operator()(int&&)
    {
        std::cout << "rvalue";
    }
};

std::function<void(int)> f{Widget()};
int x = 5;
f(x);

猜猜哪个operator()被调用 - 一个采用右值参考的人。它似乎是设计的。这种行为背后的理由是什么?

1 个答案:

答案 0 :(得分:10)

是和否。是的,参数被转发。但是,不会,根据您在调用时提供的参数来完成重载解析 - 它是基于std::function的模板参数完成的。

std::function<void(int)>表示您有一个可调用的int,其隐式为int rvalue。使用Widget类型的左值调用int会优先int&&超过int const&重载,这就是选择该值的原因。一旦您选择了想要function的对象,那么调用实际的void(int)对象并不重要 - 这是首选的重载。

实际的调用操作符的行为就像:

struct widget_function {
    void operator()(int arg) const {
//  ~~~~~           ~~~~
        w_(std::forward<int>(arg));
//                      ~~~
    }

    Widget w_;
};

带下划线的部分来自您提供给std::function的签名。您可以看到f(x)f(5)最终都会从operator()调用相同的Widget

简而言之,std::function<Sig>类型会删除满足Sig的单个重载。它不会键入擦除整个过载集。您要求void(int),因此您获得了void(int)且只有void(int)