C++11 неоднозначная ошибка с двумя операторами (один lvalue второй rvalue)
ОБНОВЛЕНИЕ внизу.
Я хочу, чтобы make void tree::operator = ( tree t) использовал значение rvalue (в этом случае, в общем, я хочу обрабатывать их по- разному из-за эффективности)
Я кодировал его, использовал std:: move, чтобы убедиться, что он будет использовать rvalue, но компилятор говорит, что не знает, какой оператор выбрать. Разве он не должен выбрать это, используя rvalues?
Код:
void tree::operator = ( tree&& t )
{
std::swap(this->pntr, t.pntr);
}
void tree::operator = ( tree t )
{
*this = std::move(t);
}
Ошибка компилятора:
tree.cpp:23:9: error: use of overloaded operator '=' is ambiguous (with operand types 'tree' and 'typename remove_reference<tree &>::type' (aka 'tree'))
*this = std::move(t);
~~~~~ ^ ~~~~~~~~~~~~
tree.cpp:16:12: note: candidate function
void tree::operator = ( tree&& t )
^
tree.cpp:21:12: note: candidate function
void tree::operator = ( tree t )
^
1 error generated.
Я использую clang-503.0.38. (но с gcc 4.8 такая же ошибка)
ОБНОВИТЬ
Хорошо, теперь у меня есть:
tree& tree::operator = ( tree&& t )
{
std::swap(this->pntr, t.pntr);
}
tree& tree::operator = ( const tree & t )
{
*this = tree(t); // tree:tree( const tree& t )
}
И это работает. Завтра я опубликую то, что я узнал из этого, как Ответ.
2 ответа
Вы можете кодировать только одно дерево версий::operator=(tree t), которое реализовано с помощью идиомы копирования и замены, в то время как предусмотрены конструктор копирования и конструктор перемещения.
Таким образом, клиент класса может выбрать назначение копирования, например:
tree1 = tree2;
, в то время как можно также выбрать назначение перемещения, например:
tree1 = std::move(tree2);
У вашего кода есть несколько проблем:
Оператор присваивания должен возвращать ссылку на сам объект. То есть должен вернуться
tree&
неvoid
,И то и другое
tree::operator=( tree other )
а такжеtree::ooperator( tree&& other )
может принимать значения, поэтому перегрузки неоднозначны. Если вам нужно / нужно только присвоение rvalue, ваше присвоение rvalue, основанное на копировании и обмене, является правильным, но если вам нужны как значения rvalue, так и значения lvalue, вы должны предоставлять только путем присвоения значения и использовать для этого идиому копирования и замены:tree& tree::operator=( tree other ) { using std::swap; //Enable ADL (Not strictly neccesary, but good practice) swap( *this , other ); return *this; }
Обратите внимание, что вы должны написать кастом
swap()
функция, чтобы сломать потенциальную бесконечную рекурсию наstd::swap()
реализация по умолчанию. Прочтите эту ветку, чтобы узнать больше о копировании и идиом обмена.