【问题标题】:Understanding std::forward了解 std::forward
【发布时间】:2015-08-25 13:08:54
【问题描述】:

为什么编译器无法推断出std::forward 的模板参数?

我的意思是:

#include <memory>
#include <iostream>

struct X{};

struct A{
    A( const X& ) { std::cout << "cpy ctor\n"; }
    A( X&& ) { std::cout << "move ctor\n"; }
};

X foo() { return {}; }

template<typename T,typename Arg>
T* factory( Arg&& a )
{
    return new T(std::forward(a));
    // ----------^^^^^^^^^^^^^^^ error: can't deduce template parameter
}

int main()
{
    factory<A>(foo());
}

我知道这是一种设计选择(由于std::forward 的定义中的std::remove_reference)避免用户忘记指定类型。我无法得到的是:为什么它的实施方式可以防止扣除?为什么编译器不只是将forward 的模板参数推断为Arg

【问题讨论】:

  • 你能澄清一下这个问题吗?您是在问为什么选择该设计来防止推理推理,或者为什么它的实现方式可以防止推理?
  • 手动指定类型的目的是让forward可以决定是否应该movea。模板参数推导可以让您确定a 的类型,但不能确定是否应该移动它。
  • @Angew 第二个。

标签: c++ c++11 perfect-forwarding


【解决方案1】:

std::forward 声明如下:

template< class T >
T&& forward( typename std::remove_reference<T>::type& t );

typename std::remove_reference&lt;T&gt;::type 是一个非推断上下文。编译器无法知道应该推导出哪个T,因为它不理解type 成员类型和给定T 之间的语义联系。它需要搜索所有类型以找到匹配项并能够以某种方式消除冲突。这是不合理的,所以标准不允许。

【讨论】:

  • 是的,这就是我想要的。我认为阅读this 将完成剩下的工作。
【解决方案2】:

您必须为forward 指定类型的原因是,在函数内部a 会发生什么情况:

template<typename T,typename Arg>
T* factory( Arg&& a )
{
    // 'a' is always an lvalue here

由于a始终是左值,a 本身没有足够的信息来确定它是作为左值还是右值传入。 信息只能通过Arg 类型获得,这将是XX&amp;。如果没有这些额外的类型信息,就不可能知道a 是否必须作为左值或右值转发......这就是你需要提供它的原因:

    return new T(std::forward<Arg>(a));
}

【讨论】:

  • 好吧,我认为 OP 提出了一个稍微不同的问题。无论如何都会把它留在这里。
  • 是的,我的错。这个问题不是很清楚。我希望编辑有助于找出我的麻烦。
【解决方案3】:

来自 C++11 标准:

14.8.2.5 从类型推导模板参数

未推断的上下文是:

— 使用限定 ID 指定的类型的嵌套名称说明符

— decltype-specifier 的表达式。

——一个非类型模板参数或一个绑定在其中的数组 子表达式引用模板参数。

——函数参数类型中使用的模板参数 具有在调用中使用的默认参数的参数 正在为哪个参数进行推导。

等等……

std::forward 声明如下:

template<typename _Tp> constexpr _Tp&& forward(typename std::remove_reference<_Tp>::type& __t) noexcept

根据上面的第一句话: typename std::remove_reference&lt;_Tp&gt;::type 是非推断上下文。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-25
    • 2018-07-05
    • 2016-07-08
    • 2014-10-15
    • 2014-06-12
    • 1970-01-01
    • 2015-05-03
    相关资源
    最近更新 更多