2016-01-18 1 views
3

У меня есть простая оболочка RAII для управления определенным ресурсом. Вот интерфейс:Как удалить оператор присваивания перемещения и сохранить совместимость с контейнерами std?

struct ResourceWrapper 
{ 
    explicit ResourceWrapper(RESOURCE resource); 
    ResourceWrapper(const ResourceWrapper& other); 
    ResourceWrapper& operator=(const ResourceWrapper& other); 
    ~ResourceWrapper(); 

    ResourceWrapper(ResourceWrapper&& other) = delete; 
    ResourceWrapper& operator=(ResourceWrapper&& other) = delete; 
}; 

Проблема здесь состоит в том, что я больше не может использовать этот класс с std контейнеров и алгоритмов, как только я явно удалить оператор присваивания двигаться. И, очевидно, мне нужно либо удалить, либо правильно реализовать его, как я только что усвоил.

Другой альтернативой было бы реализовать назначение перемещения посредством обычного оператора присваивания, но я не уверен, как это сделать должным образом. Полагаю, мне нужно что-то вроде std::remove_reference? Интересно, удалит ли он одну ссылку слишком много и повлечет за собой создание ненужного временного объекта.

+0

Вы предотвращаете перемещение, но способствуете копированию? звучит странно. что это за ресурс? –

+0

@DavidHaim: да, точно. Неважно, какой ресурс он есть, я просто хочу уйти с минимальным количеством кода. Я не могу отказаться от копирования, но я могу переехать. –

+1

Путь к переезду - это не определять его, то, что вы сделали, это не «переместить», это «яд», поэтому копирование rvalues ​​невозможно ». Это не то же самое. –

ответ

12

И, очевидно, мне нужно либо удалить, либо правильно реализовать его, как я только что усвоил.

Нет, вы этого не сделаете.

В вашем классе есть пользовательский конструктор копирования, оператор копирования и деструктор, поэтому компилятор будет не определить для вас оператор присваивания переадресации.

Так что просто прекратите пытаться удалить его, и класс будет скопирован, а не перемещен.

С удален операции перемещения вы не можете скопировать значения типа, то есть становится чрезвычайно сложно использовать в качестве типа значения (в том числе в контейнерах). С no операции перемещения он просто сделает глубокую копию rvalues, которая безопасна и, вероятно, что вы хотите.

Удаление операций перемещения имеет смысл только в том случае, если вы хотите, чтобы класс был полностью несъемным и не скопировался, например. что-то вроде типа мьютекса, где идентификация объекта важна, а не его значение. Никогда не имеет смысла иметь тип копирования с удаленными ходами.

+0

Я сильно подозреваю, что это не происходит, и ошибка, над которой я работаю, вызвана назначением перемещения по умолчанию. Думаю, мне нужно будет правильно выполнить назначение переноса, чтобы проверить эту гипотезу? –

+1

@ VioletGiraffe Чтобы проверить такую ​​гипотезу (которая укажет на ошибку в используемом компиляторе), вы можете просто реализовать перемещения в терминах копий: 'ResourceWrapper (ResourceWrapper && other): ResourceWrapper (other) {}'. Обратите внимание, что последний действительно вызовет копию ctor. – Angew

+0

@Angew: конструктор не проблема, задание. Разве это не 'ResourceWrapper & operator = (ResourceWrapper && other) {return * this = other;}' recursion? Или это будет только рекурсия, если я использую 'return * this = std :: forward (other)'? –

Смежные вопросы