I have some class and wrapper around it. For example:
#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);
}
In the case when c
is inner
output is correct:
rvalue: r
lvalue: l
But when c
is wrapper
output is not correct:
rvalue: r
rvalue: l
Why l-value became r-value?
And what the difference if wrapper
's f
definition on line (1)
would be:
template<typename _T>
void f(_T v) { i.f(std::forward<T>(v)); } //without &&
Because you're doing:
template<typename _T>
void f(_T&& v) { i.f(std::forward<T>(v)); } //(1)
^
T, not _T
You're always just using T
, not the deduced type of v
. For added clarity, you're actually doing:
template <typename _T>
void f(_T&& v) {
i.f(std::forward<std::string>(v));
}
And the type of std::forward<std::string>(v)
is string&&
.
For your second question:
template<typename _T>
void f(_T v) { i.f(std::forward<T>(v)); } //without &&
Since _T
will never deduce as a reference type here, std::forward<T>(v)
will be equivalent to std::move(v)
- it's just a cast to rvalue reference.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.