【问题标题】:Forwarding params in C++C++ 中的转发参数
【发布时间】:2015-04-23 17:03:47
【问题描述】:

我有一些类和包装器。例如:

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

cinner的情况下输出正确:

rvalue: r
lvalue: l

但是当cwrapper 时输出不正确:

rvalue: r
rvalue: l

为什么左值变成右值?

如果wrapperf(1) 线上的定义有什么区别:

    template<typename _T>
    void f(_T v) { i.f(std::forward<T>(v)); } //without &&

【问题讨论】:

  • std::forward&lt;_T&gt;(v)。此外,您使用的是保留标识符。
  • @T.C.:答案不会进入 cmets
  • @T.C.我认为使用_TT 只会导致类型不匹配时出现相同错误的不同位置。为什么它会导致将左值转换为右值?那么第二个问题和&amp;&amp;呢?删除它们不会影响任何事情。
  • _T 是保留标识符。它的使用使您的整个程序格式错误。作为一个简单的规则,避免以_ 开头的标识符,并且在标识符中的任何地方都没有__,并且您将避免遇到(几乎所有?)标准保留的标识符。 (实际规则保留的标识符比这要少,但这是一个简单的足够规则)

标签: c++ class templates c++11 c++-standard-library


【解决方案1】:

因为你在做:

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&lt;std::string&gt;(v)的类型是string&amp;&amp;

第二个问题:

template<typename _T>
void f(_T v) { i.f(std::forward<T>(v)); } //without &&

由于_T 永远不会在此处推断为引用类型,std::forward&lt;T&gt;(v) 将等效于 std::move(v) - 它只是对右值引用的强制转换。

【讨论】:

  • void f(_T&amp; v) { i.f(std::forward&lt;T&gt;(v)); } 的情况如何?同样的行为。
  • @lorond 同样,_TT。如果你更正了,它只是一个无操作 - std::forward&lt;_T&gt;(v) 只是 v 用于左值引用。
  • 我的错。使用&amp;&amp;_T 可以正常工作。但是void f(_T&amp; v) { i.f(std::forward&lt;_T&gt;(v)); }void f(_T v) { i.f(std::forward&lt;_T&gt;(v)); } 都产生右值。为什么?我认为在这两种情况下它都必须是左值,因为没有 &amp;&amp; 右值定义。
  • @lorond 对不起,我第一次说错了。如果您只有f(_T&amp; v),那么_T 将推断为std::string,因此您的forward 将转发一个右值引用。不同之处在于,在f(_T&amp;&amp; v) 中,对于左值引用,_T 推导出为std::string&amp;
猜你喜欢
  • 1970-01-01
  • 2010-09-14
  • 2011-10-31
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多