Позвольте Memeber
быть классом, и давайте предположим, что я понятия не имею, поддерживает ли он или нуждается в семантике перемещения. Скажем, для всех намерений и целей это еще даже не указано / написано. Какой случай функций SetMember
следует реализовать в классе Outer
, в котором Member
является членом?
Если бы Member
не поддерживал ход, я бы сделал это:
class Member {
public:
Member(Member&&) = delete;
Member& operator=(Member&&) = delete;
};
class Outer {
Member m_member;
public:
void SetMember(const Member& o) { m_member = o.m_member; } // makes a copy
};
И если Member
поддержит движение, я сделаю это:
class Member {
public:
Member(Member&&);
Member& operator=(Member&&);
};
class Outer {
Member m_member;
public:
void SetMember(Member o) { m_member = std::move(o.m_member); } // makes a copy if needed
};
Но так как я не знаю, есть ли у него движение или нет, мне нужно реализовать оба? Как это:
class Outer {
Member m_member;
public:
void SetMember(const Member& o) { m_member = o.m_member; } // makes a copy
void SetMember(Member&& o) { m_member = std::move(o.m_member); } // makes no copy
};
Или я должен это сделать?
class Outer {
Member m_member;
public:
template <class T>
void SetMember(T&& o) { m_member = std::forward<T>(o.m_member); }
};
Почему я не доволен этими двумя решениями:
- В первом решении я вижу дублирование кода, которое необходимо только потому, что я не знаю некоторых деталей реализации
Member
, а именно, поддерживает ли он перемещение или нет.
- Второе решение оставляет меня с ошибками компиляции вместо ошибок intelli-смысла всякий раз, когда я пытаюсь использовать
SetMember
для неправильного типа. Также мне нужен шаблон только потому, что некоторые детали реализации Member
.
Как правильно справиться с этой ситуацией?