Ответ 1
Insert(key, Value()); // Compiler error here
key
здесь Key&& key
- это значение l! У него есть имя, и вы можете взять его адрес. Это только тот тип этого lvalue - "rvalue reference to key
".
Вам нужно передать значение rvalue, и для этого вам нужно использовать std::move
:
Insert(std::move(key), Value()); // No compiler error any more
Я понимаю, почему это противоречит интуиции! Но как только вы различаете и ссылку rvalue (которая является ссылкой, привязанной к rvalue) и фактическим значением r, становится понятнее.
Изменить: настоящая проблема здесь - использовать ссылки rvalue. Имеет смысл использовать их в шаблоне функций, где выводится тип аргумента, поскольку это позволяет аргументу связываться с ссылкой на lvalue или ссылкой на rvalue из-за правил сбрасывания ссылок. См. Эту статью и видео для почему: http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers
Однако в этом случае тип ключа не выводится при вызове функции, поскольку он уже был определен классом при создании экземпляра FastHash<std::string, ... >
. Таким образом, вы действительно назначаете использование ссылок rvalue и, таким образом, используя std::move
, исправляет код.
Я бы изменил ваш код на то, что параметры берутся по значению:
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)
{
// ...
}
Не беспокойтесь о дополнительных копиях из-за использования аргументов значения - они часто оптимизируются компилятором.