В своем разговоре GoingNative 2013 Скотт Мейерс отметил, что std::move
не гарантирует, что сгенерированный код действительно выполнит ход.
Пример:
void foo(std::string x, const std::string y) {
std::string x2 = std::move(x); // OK, will be moved
std::string y2 = std::move(y); // compiles, but will be copied
}
Здесь конструктор перемещения не может быть применен, но из-за разрешения перегрузки вместо него будет использоваться обычный конструктор копирования. Этот резервный вариант может иметь решающее значение для обратной совместимости с кодом С++ 98, но в приведенном выше примере это скорее всего не то, что предполагал программист.
Есть ли способ принудительно заставить конструктор перемещения вызываться?
Например, предположим, что вы хотите переместить огромную матрицу. Если ваше приложение действительно зависит от перемещаемой матрицы, было бы замечательно сразу же получить ошибку компиляции, если переход невозможен. (В противном случае проблема производительности может легко проскальзывать через модульные тесты, и вы узнаете только после некоторого профилирования.)
Позволяет выполнить этот гарантированный ход strict_move
. Я хотел бы иметь возможность писать код следующим образом:
void bar(Matrix x, const Matrix y) {
Matrix x2 = strict_move(x); // OK
Matrix y2 = strict_move(y); // compile error
}
Возможно ли это?
Edit:
Спасибо за отличные ответы! Были некоторые законные просьбы, чтобы уточнить мой вопрос:
- Должен ли
strict_move
сбой, если вход const? - Если
strict_move
завершится сбой, если результат не приведет к фактической операции перемещения (даже если копия может быть такой же быстрой, как и перемещение, например,const complex<double>
)? - Как?
Моя оригинальная идея была очень расплывчатой: я считал примеры Скотта Мейерса довольно тревожными, поэтому я подумал, возможно ли компилятор предотвратить такие непреднамеренные копии.
Скотт Мейерс упомянул в своем разговоре, что предупреждение общего компилятора не является вариантом, так как это приведет к тому, что огромное количество будет ложным срабатыванием. Вместо этого я хочу сообщить компилятору что-то вроде "Я на 100% уверен, что это должно всегда приводить к операции перемещения, а копия слишком дорогая для этого конкретного типа".Таким образом, я бы беззастенчиво сказал, что strict_move
должен завершиться неудачей в обоих случаях. Между тем я не уверен, что было бы лучше. Другими аспектами, которые я не рассматривал, является noexcept
.
С моей стороны точная семантика strict_move
открыта. Все, что помогает предотвратить некоторые немые ошибки во время компиляции без серьезных недостатков, - это хорошо.