模板中的右值引用和常量左值引用之间的重载

Overload between rvalue reference and const lvalue reference in template

本文关键字:引用 之间 重载 常量      更新时间:2023-10-16

我想根据参数是否是临时对象重载两个函数,所以我编写了这样的代码:

#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);
}

输出变为:

&&
&&

怎么了?使用模板时如何优化可移动的临时对象?

编辑:

实际上,这是我阅读 Primer 时C++测试代码。它说:

template <typename T> void f(T&&);       // binds to nonconst rvalues
template <typename T> void f(const T&);  // lvalues and const rvalues

经过我的实验,这本书似乎在这里犯了一个错误。

template <typename T>
void f(T &&)
{
  std::cout << "&&" << std::endl;
}

使用通用转发引用,并允许任何具有引用折叠的类型。

您必须使用带有无推导上下文的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));
}

现场示例