我有一些类和包装它。例如:
$(document).on('click', ".add-gc-field", function () {
if ($(this).next('ul').length) {
console.log(this);
$(this).next('ul').append('<li><input /><p class="add-gc-field"><i class="fa fa-plus"></i></p> </li>');
} else {
console.log(this)
$(this).after('<ul><li><input /><p class="add-gc-field"><i class="fa fa-plus"></i></p> </li></ul>');
}
});
如果#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
为什么l值变为r值?
rvalue: r
rvalue: l
wrapper
f
行(1)
定义的区别是:
template<typename _T>
void f(_T v) { i.f(std::forward<T>(v)); } //without &&
答案 0 :(得分:3)
因为你正在做:
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)
- 它只是一个转换为右值引用。