编译器一直抱怨我试图将左值绑定到右值引用,但我看不出怎么做。我是C++11新手,移动语义等,所以请容忍我。
我有这个功能:
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.
}
它调用这个方法:
template <typename Key, typename Value, typename HashFunction, typename Equals>
void FastHash<Key, Value, HashFunction, Equals>::Insert(Key&& key, Value&& value)
{
// ...
}
我不断收到如下错误:
cannot convert argument 1 from 'std::string' to 'std::string &&'
key
在操作符重载中不是被定义为右值吗?为什么它被重新解释为左值?
1条答案
按热度按时间deyfvvtc1#
key
这里是Key&& key
-这是一个左值!它有一个名字,你可以接受它的地址。只是那个左值的类型是“Key
的右值引用”。你需要传入一个右值,为此你需要使用
std::move
:我可以理解为什么这是违反直觉的!但是一旦你区分了右值引用(这是一个绑定到右值的引用)和实际的右值,它就变得更清晰了。
**编辑:**这里真实的的问题是使用右值引用。在函数模板中使用它们是有意义的,其中参数的类型被推导出来,因为这允许参数绑定到左值引用或右值引用,这是由于引用折叠规则。请参阅这篇文章和视频了解原因:http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
然而,在这种情况下,Key的类型在调用函数时并没有推导出来,因为它已经在示例化
FastHash<std::string, ... >
时由类确定了。因此,您实际上是规定了使用右值引用,因此使用std::move
修复了代码。我会把你的代码改为参数是按值取的:
不要太担心由于使用值参数而导致的额外副本-这些经常被编译器优化。