【问题标题】:Overload between rvalue reference and const lvalue reference in template模板中右值引用和 const 左值引用之间的重载
【发布时间】: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&amp;&amp; 本身是最佳的,因为它绑定到所有内容并允许您恢复用作参数的表达式的值类别
  • @PiotrS。例如,如果它将变量 i 绑定到 const T&,并将表达式 i + 1 绑定到 T&&,那么我可以从 i + 1 生成的临时对象中移动资源。
  • 这就是为什么有条件移动,即std::forward&lt;T&gt;,取决于为T 推导出的类型,它要么移动,要么根本不移动。您不必为右值显式使用std::move。请注意T&amp;&amp; 其中T 是一个类型模板参数是一个转发引用,其行为不同于常规右值引用
  • @PiotrS。当我对函数参数使用右值引用时,我希望这个参数总是绑定到临时对象。但在这种情况下,它也绑定到变量。
  • T&amp;&amp; with T 是一个类型模板参数是一个转发引用,而不是一个右值引用,阳光下的一切都可以受转发参考约束

标签: c++ templates c++11 rvalue-reference


【解决方案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,... 在我理解这种行为之前,我似乎必须了解更多。 -_-||
猜你喜欢
  • 2017-03-26
  • 1970-01-01
  • 1970-01-01
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
  • 2018-02-20
  • 2017-04-13
  • 1970-01-01
相关资源
最近更新 更多