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() реализация по умолчанию. Прочтите эту ветку, чтобы узнать больше о копировании и идиом обмена.

Другие вопросы по тегам