Я пишу небольшую обертку вокруг библиотеки, которая использует ручки.C++ move операторов класса
Основные виды использования этой библиотеки являются:
int handle;
createHandle(1, &handle)
doSomethingWithHandle(handle);
// ...
destroyHandle(handle);
Я сделал класс-обертку следующие принципы RAII:
Handle::Handle()
{
createHandle(1, &m_handle);
}
Handle::~Handle()
{
if(m_handle!= 0)
destroyHandle(m_handle);
}
Handle::Handle(Handle&& h) :
m_handle(h.m_handle)
{
h.m_handle = 0;
}
Handle& Handle::operator=(Handle&& h)
{
m_handle = h.m_handle;
h.m_handle = 0;
return *this;
}
// copy constructor and copy assignment operator are explicitely deleted
Это работает, однако, много а классы зависит от этих оберток, что означает каждый раз, когда у класса есть элемент «Ручка», я должен явно писать операторы присваивания конструктора перемещения/перемещения:
SomeClass::SomeClass(SomeClass&& s) :
m_handle(std::move(s.m_handle))
{
}
SomeClass& SomeClass::SomeClass(SomeClass&& s)
{
m_handle = std::move(s.m_handle);
return *this;
}
Это, конечно, не сложно сделать, но мне интересно, есть ли способ избежать этого, потому что это много избыточного кода.
Если это невозможно, почему операторы перемещения не генерируются компилятором? Давайте возьмем следующие строки:
SomeClass a;
m_vector.push_back(a);
В этом случае SomeClass не копируемая поэтому компилятор будет иметь ошибку, потому что a.m_handle у операторов копирований удаляются. Значит, мы должны их перемещать. Но если мы это сделаем, разве это не значит, что мы хотим переместить всех членов (если мы не можем их скопировать)?
Редактировать: Я просто что-то пробовал и, похоже, работает, просто объявите операторы перемещения, используя значение по умолчанию. Полагаю, это путь. Но вопрос «почему» остается.
Edit2: Другой пример
class Test
{
public:
Test()
{
m_vec.resize(10);
}
Test(const Test&) = delete;
Test& operator=(const Test&) = delete;
//Test(Test&&) = default;
//Test& operator=(Test&&) = default;
void cout()
{
std::cout << m_vec.size() << std::endl;
}
private:
std::vector<int> m_vec;
};
int main()
{
Test a;
std::vector<Test> v;
v.push_back(std::move(a));
v[ 0 ].cout();
}
Пожалуйста показать [mcve] (/ помощь/mcve), который включает в себя остальную часть 'SomeClass'. Обычно Handle не должно препятствовать генерации оператора присваивания по умолчанию и конструктора. – MikeMB
Возможно, вы сможете создавать классы, следуя правилу нуля (создатели компилятора с копированием/перемещением, операторы присваивания копий/перемещений и деструктор) –
Вместо написания пользовательской оболочки вы можете использовать ['std :: unique_ptr'] (http : //en.cppreference.com/w/cpp/memory/unique_ptr) с пользовательским удалением, который вызывает 'destroyHandle()'. –