模板中右值引用和 const 左值引用之间的重载
Posted
技术标签:
【中文标题】模板中右值引用和 const 左值引用之间的重载【英文标题】:Overload between rvalue reference and const lvalue reference in template 【发布时间】:2015-01-08 08:38:04 【问题描述】:我想根据参数是否为临时对象来重载两个函数,所以我写了这样的代码:
#include <iostream>
void f(int &&)
std::cout << "&&" << std::endl;
void f(const int&)
std::cout << "const &" << std::endl;
int main()
int i;
f(i);
f(i + 1);
它正确地输出:
const &
&&
但是,当我将代码更改为使用这样的模板时:
#include <iostream>
template <typename T>
void f(T &&)
std::cout << "&&" << std::endl;
template <typename T>
void f(const T&)
std::cout << "const &" << std::endl;
int main()
int i;
f(i);
f(i + 1);
输出变成:
&&
&&
有什么问题?使用模板时如何优化可移动临时对象?
编辑:
其实这是我看C++ Primer时的测试代码。它说:
template <typename T> void f(T&&); // binds to nonconst rvalues
template <typename T> void f(const T&); // lvalues and const rvalues
经过我的实验,这本书似乎在这里犯了一个错误。
【问题讨论】:
“如何在使用模板时优化可移动临时对象”是什么意思?T&&
本身是最佳的,因为它绑定到所有内容并允许您恢复用作参数的表达式的值类别
@PiotrS。例如,如果它将变量 i 绑定到 const T&,并将表达式 i + 1 绑定到 T&&,那么我可以从 i + 1 生成的临时对象中移动资源。
这就是为什么有条件移动,即std::forward<T>
,取决于为T
推导出的类型,它要么移动,要么根本不移动。您不必为右值显式使用std::move
。请注意T&&
其中T
是一个类型模板参数是一个转发引用,其行为不同于常规右值引用
@PiotrS。当我对函数参数使用右值引用时,我希望这个参数总是绑定到临时对象。但在这种情况下,它也绑定到变量。
T&&
with T
是一个类型模板参数是一个转发引用,而不是一个右值引用,阳光下的一切都可以受转发参考约束
【参考方案1】:
template <typename T>
void f(T &&)
std::cout << "&&" << std::endl;
使用 universal 转发引用并允许任何类型的引用折叠。
你必须使用T
和没有推导上下文来将你的代码包装到一个结构中:
template <typename T>
struct helper
void f(T &&)
std::cout << "&&" << std::endl;
void f(const T&)
std::cout << "const &" << std::endl;
;
template <typename T>
void f(T &&t)
helper<typename std::decay<T>::type>().f(std::forward<T>(t));
Live example
【讨论】:
std::decay, std::forward,... 在我理解这种行为之前,我似乎必须了解更多。 -_-||以上是关于模板中右值引用和 const 左值引用之间的重载的主要内容,如果未能解决你的问题,请参考以下文章
在 C++ 中将右值引用转换为临时参数到 const 左值返回的正确方法