C++ c++;:关于转发参考的困惑

C++ c++;:关于转发参考的困惑,c++,c++11,move,move-semantics,forwarding-reference,C++,C++11,Move,Move Semantics,Forwarding Reference,我读了Scott Meyers写的关于C++11中转发引用的文章(写得非常好) 现在,请关注本文的这一部分: 因此(使用与前一示例相同的逻辑),&&表示转发引用 但是如果我尝试打这个电话: typedef vector<double> vecD; vecD vec; mem.callFunction<vecD, vecD>(sortFunc, vec); 因此,首先,请使用“转发参考”而不是“通用参考”。它更好地代表了它是什么以及它的预期用途是什么 首先要注意的是,并非

我读了Scott Meyers写的关于C++11中转发引用的文章(写得非常好)

现在,请关注本文的这一部分:

因此(使用与前一示例相同的逻辑),
&&
表示转发引用

但是如果我尝试打这个电话:

typedef vector<double> vecD;
vecD vec;
mem.callFunction<vecD, vecD>(sortFunc, vec);

因此,首先,请使用“转发参考”而不是“通用参考”。它更好地代表了它是什么以及它的预期用途是什么

首先要注意的是,并非每个
&&
都是转发引用。它也可以是右值引用

简单来说,
T&
是转发引用,当且仅当:

  • T
    是一种简单(如下所示)类型(例如
    vector&
    vector&&
    不是转发引用)
  • 并推导出
    T
在您的示例中,未推导出
Args
。这是因为在调用函数模板参数时显式指定了函数模板参数
Args

mem.callFunction<vecD, vecD>(sortFunc, vec);
                       ^~~~
在第一种情况下,
T
将被推断为
X&
,通过折叠规则:
X&&&
将变成
X&
,因此我们有一个左值引用。如你所料

在第二种情况下,
T
将被推断为
X
,通过折叠规则
X&
将成为
X&
,因此我们有一个右值参考

但当你这样称呼它时:

foo<X>(x);
foo(x);
T
不再推导。你基本上说让
T
be
X
。因此,如果
T
X
,那么
T&&
X&
,并且您有一个错误:
p
,其类型现在是
X&
,无法绑定到左值


霍尔特还补充说:


还请注意,由于sortFunc的声明,这不会 即使未指定函数模板参数也可以工作 明确地说


我倾向于同意他的观点,但我需要进一步调查以确定这一点。

通用参考从一开始就是一个糟糕的术语,现在它最终被更合适的转发参考所取代。你确定在你的电话中确实推断出了
Args
?请提供一个答案。提供的代码不完整(什么是
sort\u vec
?),当然也不是最小的。@bolov他们几乎只是想看看相关的代码@每个人都是对的:1。您的代码片段中缺少一些部分,2。你的代码包含很多与你的问题无关的东西,3。这些与你的问题完全无关,4。代码可以是最小的,并且可以为编译器工作。对于您的问题来说,这可能是一个很好的MCVE,它有25行长。还要注意,由于
sortFunc
的声明,即使您没有明确指定函数模板参数,这也不起作用。我想我理解您的答案,但我的下一个问题是:有一种方法可以使我的代码“转发可引用”(并因此使
Args
类型推断)?@justHelloWorld乍一看我会说不(至少不是没有一些讨厌的丑陋的黑客)。你需要为
sortFunc
指定
Args
。也许如果你使
memFunc
成为最后一个参数(不知道是否可能)因此,先进行
Args
推断,然后它会更改
memFunc
的签名。但是你可以在
memFuc
的参数签名中添加
remove\u reference\t
。正如我所说,丑陋的黑客行为。@justHelloWorld如果你把它作为一个单独的问题发布的话(但请尽量少用)有人会想出一个好的解决方案。打开此主题的问题:
#include <functional>
#include <vector>

using namespace std;
struct MultiMemoizator {
    template <typename ReturnType, typename... Args>
    ReturnType callFunction(std::function<ReturnType(Args...)> memFunc, Args&&... args) {

    }
};

typedef vector<double> vecD;

vecD sort_vec (vecD const& vec) {
    return vec;
}

int main()
{
    vecD vec;
    std::function<vecD(vecD)> sortFunc(sort_vec);
    MultiMemoizator mem;
    mem.callFunction<vecD, vecD>(sortFunc, vec);
}
mem.callFunction<vecD, vecD>(sortFunc, vec);
                       ^~~~
struct X {};

template <class T>
auto foo(T&& p) {}
X x;
foo(x);

foo(X{});
foo<X>(x);