C++ 通用参考和本地类

C++ 通用参考和本地类,c++,forward,forwarding,perfect-forwarding,forwarding-reference,C++,Forward,Forwarding,Perfect Forwarding,Forwarding Reference,在下面的代码中,我有一个函数,它接受“通用引用”(F&&)。函数还有一个内部类,它在构造函数中接受F&的对象。在这一点上,F&仍然是一个通用的参考吗?也就是说,F是否仍被视为推断类型 换句话说,我应该在构造函数初始化列表中使用std::forward还是std::move #include "tbb/task.h" #include <iostream> #include <future> template<class F> auto Async(F&

在下面的代码中,我有一个函数,它接受“通用引用”(
F&&
)。函数还有一个内部类,它在构造函数中接受
F&
的对象。在这一点上,
F&
仍然是一个通用的参考吗?也就是说,
F
是否仍被视为推断类型

换句话说,我应该在构造函数初始化列表中使用
std::forward
还是
std::move

#include "tbb/task.h"
#include <iostream>
#include <future>

template<class F>
auto Async(F&& f) -> std::future<decltype(f())>
{
    typedef decltype(f()) result_type;

    struct Task : tbb::task
    {
        Task(F&& f) : f_(std::forward<F>(f)) {} // is forward correct here?

        virtual tbb::task* execute()
        {
            f_();
            return nullptr;
        }

        std::packaged_task<result_type()> f_;
    };

    auto task = new (tbb::task::allocate_root()) Task(std::forward<F>(f));
    tbb::task::enqueue(*task);
    return task->f_.get_future();
}


int main()
{
    Async([]{ std::cout << "Hi" << std::endl; }).get();
}
#包括“tbb/task.h”
#包括
#包括
模板
自动异步(F&&F)->std::future
{
typedef decltype(f())结果类型;
结构任务:tbb::任务
{
Task(F&&F):F_(std::forward(F)){}//这里的forward正确吗?
虚拟tbb::任务*执行()
{
f_u2;();
返回空ptr;
}
std::打包任务f;
};
自动任务=新建(tbb::task::allocate_root())任务(std::forward(f));
tbb::任务::排队(*任务);
返回任务->f_.get_future();
}
int main()
{

异步([]{std::coutctor不是一个通用引用,而是一个bog标准右值引用或左值引用。构造的问题是您不知道是哪个,只是它镜像了
异步
(这可能足够了)

为了成为一个通用引用,必须为该调用推导类型,而不是更早地为某个相关调用推导类型

std::forward
i仍然适用于此,因为outer functions参数确实应该传递给具有保留的move-/copy语义的已创建对象

此时,
F&&
是否仍然是一个通用的参考?即,
F
是否仍然被认为是一个推断类型

这种混乱正是我不喜欢“普遍参照”这个词的原因

我更喜欢从左值引用和右值引用的角度来理解代码,以及引用折叠和模板参数推断的规则

当使用类型为
L
的左值调用函数时,参数
F
将被推断为
L&
,通过引用,折叠规则
F&&
只是
L&
。在
任务
构造函数中,没有任何变化,
F&
仍然是
L&
,因此构造函数采用左值引用绑定到传递给
Async
的左值的ence,因此您不想移动它,
forward
是合适的,因为它保留了值类别,将左值作为左值转发。(从左值移动会让
Async
的调用方感到惊讶,因为他们不希望左值被静默地移动。)

当使用类型为
R
的右值调用函数时,参数
F
将被推断为
R
,因此
F&&
R&
。在
任务
构造函数中,没有任何变化,
F&
仍然是
R&
,因此构造函数采用绑定到右值pa的右值引用sed为
Async
,因此可以将其移动,但
forward
也很合适,因为这样会保留值类别,将右值作为右值转发


上周在CppCon上,赫伯·萨特宣布“通用参考”的首选术语现在是转发参考,因为这更好地描述了它们的用途。

酷孩子们称它们现在不是通用参考。(Cos)感谢您的解释。认识到std::forward仅仅意味着保留值类别带来了很多清晰。