Lvalue to rvalue reference binding

Kristian D'Amato

The compiler keeps complaining I'm trying to bind an lvalue to an rvalue reference, but I cannot see how. I'm new to C++11, move semantics, etc., so please bear with me.

I have this function:

template <typename Key, typename Value, typename HashFunction, typename Equals>
Value& FastHash<Key, Value, HashFunction, Equals>::operator[](Key&& key)
{
    //  Some code here...

    Insert(key, Value()); // Compiler error here

    //   More code here.
}

which calls this method:

template <typename Key, typename Value, typename HashFunction, typename Equals>
void FastHash<Key, Value, HashFunction, Equals>::Insert(Key&& key, Value&& value)
{
    // ...
}

I keep getting errors like the following:

cannot convert argument 1 from 'std::string' to 'std::string &&'

on the Insert() call. Isn't key defined as an rvalue in the operator overload? Why is it being reinterpreted as an lvalue?

user2428400
Insert(key, Value()); // Compiler error here

key here is Key&& key - this is an lvalue! It has a name, and you can take its address. It's just that type of that lvalue is "rvalue reference to Key".

You need to pass in an rvalue, and for that you need to use std::move:

Insert(std::move(key), Value()); // No compiler error any more

I can see why this is counter-intuitive! But once you distinguish between and rvalue reference (which is a reference bound to an rvalue) and an actual rvalue, it becomes clearer.

Edit: the real problem here is using rvalue references at all. It makes sense to use them in a function template where the type of the argument is deduced, because this allows the argument to bind to either an lvalue reference or an rvalue reference, due to reference collapsing rules. See this article and video for why: http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers

However, in this case the type of Key is not deduced when the function is called, as it has already been determined by the class when you instantiated FastHash<std::string, ... >. Thus you really are prescribing the use of rvalue references, and thus using std::move fixes the code.

I would change your code to that the parameters are take by value:

template <typename Key, typename Value, typename HashFunction, typename Equals>
Value& FastHash<Key, Value, HashFunction, Equals>::operator[](Key key)
{
    //  Some code here...

    Insert(std::move(key), Value());

    //   More code here.
}

template <typename Key, typename Value, typename HashFunction, typename Equals>
void FastHash<Key, Value, HashFunction, Equals>::Insert(Key key, Value value)
{
    // ...
}

Don't worry too much about extra copies due to use of value arguments - these are frequently optimised out by the compiler.

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Why can you indirectly bind an rvalue to an lvalue reference but not directly?

来自分类Dev

使用rvalue / lvalue了解模板参数推导

来自分类Dev

将Lvalue传递给RValue的参数

来自分类Dev

为什么Rvalue无法绑定Lvalue引用?

来自分类Dev

强制转换后是Rvalue还是Lvalue

来自分类Dev

书中“ rvalue”和“ rvalue reference”之间的混淆

来自分类Dev

如何从C ++中的rvalue和lvalue参数移开?

来自分类Dev

为什么const lvalue引用可以引用可变rvalue引用?

来自分类Dev

在RValue对象上调用LValue ref合格成员函数

来自分类Dev

Confusion about rvalue reference: what is its type?

来自分类Dev

GCC中的异常行为:rvalue ref和lvalue ref是协变返回类型

来自分类Dev

唯一指针:LValue引用vs RValue引用函数调用

来自分类Dev

C二进制运算符应用于LVALUE或RVALUE的宽度

来自分类Dev

带有rvalue引用参数的模板函数中的std :: is_rvalue_reference

来自分类Dev

std :: move()和std :: add_rvalue_reference()之间的区别

来自分类Dev

C ++ 11:为什么result_of可以接受函子类型作为lvalue_reference,但不能接受函数类型作为lvalue_reference?

来自分类Dev

C ++ 11:为什么result_of可以接受函子类型作为lvalue_reference,但不能接受函数类型作为lvalue_reference?

来自分类Dev

Why are the compiler errors inconsistent in gcc and clang when casting an xvalue to a non-const lvalue reference?

来自分类Dev

模板是否应该使非Rvalue-reference构造函数/赋值仅移动不同类型的参数?

来自分类Dev

nullptr rvalue如何

来自分类Dev

Storing rvalue references: should this work?

来自分类Dev

std :: bind和rvalue参考

来自分类Dev

std :: thread和rvalue参考

来自分类Dev

函数返回的结构体作为LValue

来自分类Dev

错误:“ Int”不可转换为“ @lvalue Float”

来自分类Dev

'@lvalue $ T7'与'CGPoint!'不同

来自分类Dev

C结构取消引用需要Lvalue

来自分类Dev

C , Error: Expression must be a modifiable lvalue

来自分类Dev

错误:“ Int”不可转换为“ @lvalue Float”

Related 相关文章

  1. 1

    Why can you indirectly bind an rvalue to an lvalue reference but not directly?

  2. 2

    使用rvalue / lvalue了解模板参数推导

  3. 3

    将Lvalue传递给RValue的参数

  4. 4

    为什么Rvalue无法绑定Lvalue引用?

  5. 5

    强制转换后是Rvalue还是Lvalue

  6. 6

    书中“ rvalue”和“ rvalue reference”之间的混淆

  7. 7

    如何从C ++中的rvalue和lvalue参数移开?

  8. 8

    为什么const lvalue引用可以引用可变rvalue引用?

  9. 9

    在RValue对象上调用LValue ref合格成员函数

  10. 10

    Confusion about rvalue reference: what is its type?

  11. 11

    GCC中的异常行为:rvalue ref和lvalue ref是协变返回类型

  12. 12

    唯一指针:LValue引用vs RValue引用函数调用

  13. 13

    C二进制运算符应用于LVALUE或RVALUE的宽度

  14. 14

    带有rvalue引用参数的模板函数中的std :: is_rvalue_reference

  15. 15

    std :: move()和std :: add_rvalue_reference()之间的区别

  16. 16

    C ++ 11:为什么result_of可以接受函子类型作为lvalue_reference,但不能接受函数类型作为lvalue_reference?

  17. 17

    C ++ 11:为什么result_of可以接受函子类型作为lvalue_reference,但不能接受函数类型作为lvalue_reference?

  18. 18

    Why are the compiler errors inconsistent in gcc and clang when casting an xvalue to a non-const lvalue reference?

  19. 19

    模板是否应该使非Rvalue-reference构造函数/赋值仅移动不同类型的参数?

  20. 20

    nullptr rvalue如何

  21. 21

    Storing rvalue references: should this work?

  22. 22

    std :: bind和rvalue参考

  23. 23

    std :: thread和rvalue参考

  24. 24

    函数返回的结构体作为LValue

  25. 25

    错误:“ Int”不可转换为“ @lvalue Float”

  26. 26

    '@lvalue $ T7'与'CGPoint!'不同

  27. 27

    C结构取消引用需要Lvalue

  28. 28

    C , Error: Expression must be a modifiable lvalue

  29. 29

    错误:“ Int”不可转换为“ @lvalue Float”

热门标签

归档