#include <iostream>
#include <vector>
#include <type_traits>
#include <utility>
using namespace std;
template <typename Func, typename... Args>
void proxy(Func f, Args&&... args) {
f(std::forward<Args>(args)...);
}
void real_func(vector<int> v) {
cout << "size: " << v.size() << endl;
}
void multicast_func(vector<int> v) {
proxy(real_func, std::forward<vector<int>>(v));
proxy(real_func, std::forward<vector<int>>(v));
}
int main()
{
vector<int> ints = {1, 2, 3};
multicast_func(ints);
return 0;
}
,输出为:
size: 3
size: 0
为什么不是3、3?在什么时候该左值变成右值并从中移出?
答案 0 :(得分:5)
std::forward
旨在与通用引用一起使用。
multicast_func
的参数不是通用引用,因此std::forward
毫无意义:
void multicast_func(vector<int> v) {
proxy(real_func, std::forward<vector<int>>(v));
proxy(real_func, std::forward<vector<int>>(v));
}
在这种情况下,它实际上像std::move
一样工作(因为template参数不是(左值)引用)。
答案 1 :(得分:4)
您的代码中调用的std::forward
的原型为:
template< class T >
constexpr T&& forward( typename std::remove_reference<T>::type& t ) noexcept;
以非引用类型调用时,它有效地从参数中移出了右值引用,然后将其移出。 std::vector
被确保从其移出后为空,因此size
变为0。
答案 2 :(得分:1)
在什么时候该左值变成右值并从中移出?
第一次调用v
时,real_func
被转换为右值,然后在传递给void multicast_func(vector<int> v) {
// the return type of std::forward is T&&, i.e. vector<int>&& here
// for functions whose return type is rvalue reference to objec, the return value is an rvalue
// that means v is converted to an rvalue and passed to proxy
proxy(real_func, std::forward<vector<int>>(v));
// v has been moved when passed to real_func as argument
proxy(real_func, std::forward<vector<int>>(v));
}
时被移出。
proxy
std::forward
中的用法是T&
的常规用法;根据参数是左值还是右值,模板参数将推导为T
或T&
。对于std::forward
T
将返回一个左值,对于std::forward
import { LitElement, html } from '../lib/@polymer/lit-element/lit-element.js';
将返回一个右值,因此将保留值类别。当您指定模板参数时,仅会丢失这种容量。
答案 3 :(得分:1)
std::forward
,如果未指定引用类型,则会将提供的对象转换为右值。这意味着第一个呼叫
proxy(real_func, std::forward<vector<int>>(v));
将使v
成为右值,这意味着它将把它移到real_func
中。然后,第二个调用使用从对象移出的那个,您会得到0
的大小,因为它已被清空。
如果我们看一下函数,这是有道理的。您正在呼叫的std::forward
的版本是
template< class T >
constexpr T&& forward( typename std::remove_reference<T>::type& t ) noexcept;
由于您为std::vector<int>
传递了T
,这意味着它将返回一个std::vector<int>&&
。因此,即使v
是左值,它也会转换为右值。如果要保持v
的左值性,则需要使用std::vector<int>&
。这样就给了std::vector<int>& &&
,引用折叠规则将其变成std::vector<int>&
,使您拥有左值。
答案 4 :(得分:0)
在proxy
的第一次调用中,参数vector<int> v
(在函数real_func
中)是从右值构造的,因此v
(在函数{{1}中) })为空。
但是,如果将参数的类型更改为multicast_func
,则结果将为3、3。因为尚未调用move constrctor。
cosnt vector<int> &