Предупреждение Clang, безусловно, верно.Поскольку derived
относится к типу, который отличается от типа, возвращаемого функцией, в операторе return derived;
компилятор должен рассматривать derived
как lvalue, и будет происходить его копирование.И этой копии можно избежать, написав return std::move(derived);
, явным образом превратив ее в значение.Предупреждение не говорит вам, должны ли вы сделать это.Он просто говорит вам о последствиях того, что вы делаете, и последствиях использования std::move
, и позволяет вам принять собственное решение.
Вы беспокоитесь о том, что деструктор Derived
может получить доступ кBase
состояние после перемещения, что может привести к ошибкам.Если такие ошибки возникают, то это потому, что автор Derived
допустил ошибку, а не потому, что пользователь не должен был перемещать подобъект Base
.Такие ошибки могут быть обнаружены так же, как и другие ошибки, и сообщены автору Derived
.
Почему я так говорю?Поскольку, когда автор сделал Base
общедоступный базовый класс Derived
, он пообещал пользователю, что он имеет право использовать полный интерфейс Base
всякий раз, когда взаимодействует с объектом Derived
,что включает в себя перемещение от него.Таким образом, все функции-члены Derived
должны быть готовы к тому, что пользователь мог модифицировать подобъект Base
любым способом, который позволяет интерфейс Base
.Если это нежелательно, то Base
можно сделать частным базовым классом Derived
или частным элементом данных, а не общедоступным базовым классом.