C++中的转发参数
Forwarding params in C++
我有一些 class 和包装纸。例如:
#include <iostream>
#include <string>
template<typename T>
class inner
{
public:
void f(T& v) { std::cout<<"lvalue: "<<v<<std::endl;}
void f(T&& v) { std::cout<<"rvalue: "<<v<<std::endl;}
};
template<typename T>
class wrapper
{
public:
template<typename _T>
void f(_T&& v) { i.f(std::forward<T>(v)); } //(1)
private:
inner<T> i;
};
int main()
{
wrapper<std::string> c;
//inner<std::string> c;
c.f("r");
std::string s = "l";
c.f(s);
}
在c
为inner
的情况下输出正确:
rvalue: r
lvalue: l
但是当c
为wrapper
时输出不正确:
rvalue: r
rvalue: l
为什么左值变成右值?
如果 wrapper
的 f
行 (1)
定义有什么区别:
template<typename _T>
void f(_T v) { i.f(std::forward<T>(v)); } //without &&
因为你在做:
template<typename _T>
void f(_T&& v) { i.f(std::forward<T>(v)); } //(1)
^
T, not _T
您总是只使用 T
,而不是 v
的 推导 类型。为了更加清楚,您实际上是在做:
template <typename _T>
void f(_T&& v) {
i.f(std::forward<std::string>(v));
}
而std::forward<std::string>(v)
的类型是string&&
。
第二个问题:
template<typename _T>
void f(_T v) { i.f(std::forward<T>(v)); } //without &&
由于 _T
永远不会在此处推断为引用类型,因此 std::forward<T>(v)
将等同于 std::move(v)
- 它只是对右值引用的强制转换。
我有一些 class 和包装纸。例如:
#include <iostream>
#include <string>
template<typename T>
class inner
{
public:
void f(T& v) { std::cout<<"lvalue: "<<v<<std::endl;}
void f(T&& v) { std::cout<<"rvalue: "<<v<<std::endl;}
};
template<typename T>
class wrapper
{
public:
template<typename _T>
void f(_T&& v) { i.f(std::forward<T>(v)); } //(1)
private:
inner<T> i;
};
int main()
{
wrapper<std::string> c;
//inner<std::string> c;
c.f("r");
std::string s = "l";
c.f(s);
}
在c
为inner
的情况下输出正确:
rvalue: r
lvalue: l
但是当c
为wrapper
时输出不正确:
rvalue: r
rvalue: l
为什么左值变成右值?
如果 wrapper
的 f
行 (1)
定义有什么区别:
template<typename _T>
void f(_T v) { i.f(std::forward<T>(v)); } //without &&
因为你在做:
template<typename _T>
void f(_T&& v) { i.f(std::forward<T>(v)); } //(1)
^
T, not _T
您总是只使用 T
,而不是 v
的 推导 类型。为了更加清楚,您实际上是在做:
template <typename _T>
void f(_T&& v) {
i.f(std::forward<std::string>(v));
}
而std::forward<std::string>(v)
的类型是string&&
。
第二个问题:
template<typename _T>
void f(_T v) { i.f(std::forward<T>(v)); } //without &&
由于 _T
永远不会在此处推断为引用类型,因此 std::forward<T>(v)
将等同于 std::move(v)
- 它只是对右值引用的强制转换。