为什么`const int ci = 2; std :: forward< int>(ci);`工作和如何解决/解决它? [英] Why doesn't `const int ci = 2; std::forward<int>(ci);` work and how to fix / workaround it?

查看:254
本文介绍了为什么`const int ci = 2; std :: forward< int>(ci);`工作和如何解决/解决它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简单的问题,为什么不执行以下工作(意味着 ci )?

  #include< utility> 

int main(){
const int ci = 2;
std :: forward< int>(ci);
}




prog.cpp: ()':

prog.cpp:6:23:error:没有匹配函数调用'forward(const int&)'


在编写一些模板材料时,问题就出现了,我有一个简单的类型如下。

 为了避免不必要的副本,我尽可能使用完美的转发,但这似乎是问题的根源。 template< class T> 
struct holder {
T value;

持有者(T&& val)
:value(std :: forward< T>(val))
{}
};

template< class T>
holder< T>保持(T&& val){
// T将被推导为int,因为文字'5'是一个prvalue
//可以绑定到`int& b返回保持器T(std :: forward T(val));
}

template< class T>
void foo(holder< T> const& h)
{
std :: tuple< T& t; //设计的,实际的函数需要更多的参数
std :: get< 0>(t)= std :: forward T(h.value); // h.value is`const T`
}

int main(){
foo(hold(5));
}

如果需要任何进一步的信息,请告诉我。
$非常感谢任何解决这个问题的想法。

解决方案

这:

  #include< utility> 

int main(){
const int ci = 2;
std :: forward< int>(ci);
}

不起作用,因为您不能隐藏丢弃 const std :: forward< T>(u)应解读为:


u 转为 T


你试图说:

 将一个左值`const int`转换为右值`int`。 

会抛弃 const 。为了避免丢弃 const ,您可以:

  #include<效用> 

int main(){
const int ci = 2;
std :: forward< const int>(ci);
}

这说明:

 将一个左值`const int`转换为一个右值`const int`。 

在您的代码中:

  template< class T> 
void foo(holder< T> const& h)
{
std :: tuple< T& t; //设计的,实际的函数需要更多的参数
std :: get< 0>(t)= std :: forward T(h.value); // h.value is`const T`
}

限定符 h 会影响数据成员选择表达式 h.value h.value const lvalue int 。您可以使用 forward 将其更改为 const rvalue int ,或者您可以使用 forward 在未更改的情况下传递它(作为 const lvalue int )。您可以甚至使用 forward 添加 volatile (虽然我不能想到好的原因)。



在你的例子中,我没有看到任何理由使用 forward 您将 const 关闭 h )。

  std :: get< 0>(t)= h.value; // h.value is`const T` 

您的评论甚至仍然正确。

这是一个干读,但 N2951 调查你可以和不能做的 forward 以及为什么。这是在标准化之前由 N3143 修改的,但



您可以使用向前进行的操作 :




  • 您可以将左值作为左值。


  • 您可以将更少的cv限定的表达式转发到更多的cv限定的表达式。
  • li>
  • 您可以将派生类型的表达式转换为可访问的,明确的基本类型。



使用前进





  • 您不能将更多cv限定的表达式转发到更少的cv限定的表达式。

  • 类型转换(例如将 int 转为 double )。


Simple question, why doesn't the following work (implying a copy of ci)?

#include <utility>

int main(){
  const int ci = 2;
  std::forward<int>(ci);
}

prog.cpp: In function 'int main()':
prog.cpp:6:23: error: no matching function for call to 'forward(const int&)'

The problem manifested itself while writing some template stuff, where I have a simple holder type as follows. To avoid unnecessary copies, I use perfect forwarding where possible, but that turns out to be the root of the problem it seems.

template<class T>
struct holder{
    T value;

    holder(T&& val)
        : value(std::forward<T>(val))
    {}
};

template<class T>
holder<T> hold(T&& val){
    // T will be deduced as int, because literal `5` is a prvalue
    // which can be bound to `int&&`
    return holder<T>(std::forward<T>(val));
}

template<class T>
void foo(holder<T> const& h)
{
    std::tuple<T> t;  // contrived, actual function takes more parameters
    std::get<0>(t) = std::forward<T>(h.value); // h.value is `const T`
}

int main(){
    foo(hold(5));
}

If any further information is needed, please let me know.
Any idea to circumvent this problem is greatly appreciated.

解决方案

This:

#include <utility>

int main(){
  const int ci = 2;
  std::forward<int>(ci);
}

doesn't work because you can't implicitly cast away const. std::forward<T>(u) should be read as:

Forward u as a T.

You are attempting to say:

Forward an lvalue `const int` as an rvalue `int`.

which throws away the const. To avoid throwing away the const you could:

#include <utility>

int main(){
  const int ci = 2;
  std::forward<const int>(ci);
}

which says:

Forward an lvalue `const int` as an rvalue `const int`.

In your code:

template<class T>
void foo(holder<T> const& h)
{
    std::tuple<T> t;  // contrived, actual function takes more parameters
    std::get<0>(t) = std::forward<T>(h.value); // h.value is `const T`
}

the const qualifier on h impacts the data member selection expression h.value. h.value is a const lvalue int. You can use forward to change that into a const rvalue int, or you could use forward to pass it on unchanged (as a const lvalue int). You could even use forward to add volatile (though I can't think of a good reason to).

In your example, I'm seeing no reason to use forward at all (unless you take the const off of h).

    std::get<0>(t) = h.value; // h.value is `const T`

Your comment is even still correct.

It's a dry read, but N2951 surveys what you can and can not do with forward and why. This was modified by N3143 just prior to standardization, but the use cases and rationale from are still valid and unchanged in the final N3143 formulation.

Things you can do with forward:

  • You can forward an lvalue as an lvalue.
  • You can forward an lvalue as an rvalue.
  • You can forward an rvalue as an rvalue.
  • You can forward less cv-qualified expressions to more cv-qualified expressions.
  • You can forward expressions of derived type to an accessible, unambiguous base type.

Things you can not do with forward:

  • You can not forward an rvalue as an lvalue.
  • You can not forward more cv-qualified expressions to less cv-qualified expressions.
  • You can not forward arbitrary type conversions (e.g. forward an int as a double).

这篇关于为什么`const int ci = 2; std :: forward&lt; int&gt;(ci);`工作和如何解决/解决它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆