简体   繁体   English

通用参考和本地课程

[英]Universal references and local classes

In my code below I have a function which accepts "universal reference" ( F&& ). 在我的下面的代码中,我有一个接受“通用引用”( F&& )的函数。 The function also has an inner class which accepts an object of F&& in its constructor. 该函数还有一个内部类,在其构造函数中接受F&&的对象。 Is F&& still a universal reference at that point? 那时F&&仍然是一个普遍的参考吗? Ie is F still considered to be a deduced type? F仍然被认为是推断类型?

In other words, should I use std::forward<F> or std::move in the constructor initialization list? 换句话说,我应该在构造函数初始化列表中使用std::forward<F>还是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();
}

Live demo. 现场演示。

Is F&& still a universal reference at that point? 那时F&&仍然是一个普遍的参考吗? Ie is F still considered to be a deduced type? F仍然被认为是推断类型?

This kind of confusion is why I dislike the term universal reference ... there's no such thing . 这种混乱是为什么我不喜欢通用引用一词...... 没有这样的事情

I prefer to understand code in terms of lvalue references and rvalue references, and the rules of reference collapsing and template argument deduction. 我更喜欢用左值引用和右值引用来理解代码,以及参考规则折叠和模板参数推导的规则。

When the function is called with an lvalue of type L the argument F will be deduced as L& , and by the reference collapsing rules F&& is just L& . 当使用类型L的左值调用函数时,参数F将推导为L& ,并且通过引用折叠规则F&&仅为L& In the Task constructor nothing changes, F&& is still L& so the constructor takes an lvalue reference that is bound to the lvalue passed to Async , and so you don't want to move it, and forward is appropriate because that preserves the value category, forwarding the lvalue as an lvalue. Task构造函数中没有任何更改, F&&仍然是L&构造函数采用绑定到传递给Async的左值的左值引用,因此您不想移动它,并且forward是合适的,因为它保留了值类别,将左值转发为左值。 (Moving from the lvalue would surprise the caller of Async , who would not be expecting an lvalue to get silently moved.) (从左值移动会让Async的调用者感到惊讶,他们不会期望左值可以无声地移动。)

When the function is called with an rvalue of type R the argument F will be deduced as R , and so F&& is R&& . 当使用类型R的右值调用函数时,参数F将推导为R ,因此F&&R&& In the Task constructor nothing changes, F&& is still R&& so the constructor takes an rvalue reference that is bound to the rvalue passed to Async , and so you could move it, but forward is also appropriate because that preserves the value category, forwarding the rvalue as an rvalue. Task构造函数中没有任何变化, F&&仍然是R&&所以构造函数采用绑定到传递给Async的rvalue的rvalue引用,因此你可以移动它,但forward也是合适的,因为它保留了value类,转发了rvalue作为一个左值。

At CppCon last week Herb Sutter announced that the preferred term for a "universal reference" is now forwarding reference because that better describes what they are used for. 在上周的CppCon上,Herb Sutter宣布“通用参考”的首选术语现在转发参考,因为它更好地描述了它们的用途。

The ctor is not a universal reference, but a bog-standard rvalue-reference, or an lvalue-reference. ctor 不是通用引用,而是bog标准rvalue-reference或左值引用。 Trouble with your construction is you have no idea which, just that it mirrors Async (which might be enough)! 您的构造问题是您不知道哪个,只是它镜像Async (这可能已经足够)!

In order to be a universal-reference, the type would have to be deduced for that call , and not sometime earlier for a somewhat-related call. 为了成为通用引用,必须为该调用推断出类型,而不是之前的某个相关调用。

std::forward i still appropriate there, as the outer functions argument really should be passed on to the created object with preserved move-/copy-semantics. std::forward我仍然适合那里,因为外部函数参数确实应该传递给具有保留的移动/复制语义的创建对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM