Почему С++ 17 std:: any не позволяет возвращать подвижное значение any_cast?
При реализации С++ 17 std::any
в соответствии с имеющейся спецификацией в этой вики я наткнулся на то, что казалось мне бессмысленным:
В определении свободной функции std::any_cast
, которая используется для извлечения значений из экземпляра std::any
, перегрузка для r-value (это третий):
template< class ValueType >
ValueType any_cast(any&& operand); // (3)
Теперь есть перечисленное ниже требование, которое относится к перегрузкам 2 и 3 (это означает также включение перегрузки r-значения):
2-3)
Возвращает *any_cast<std::remove_reference_t<ValueType>>(&operand)
Определение , по-видимому, не позволяет перемещать данные!
Вызов функции просто перенаправлен на перегрузку на основе указателя; информация о временном характере operand
теряется!
Предполагается ли, что я не могу уйти из какого-либо экземпляра? Это просто ошибка в wiki? Я здесь не прав?
Ответы
Ответ 1
Проблема заключается в статусе WP во время написания этого сообщения, что означает:
WP - (Рабочий документ). Предлагаемая резолюция не была принята в качестве технического исправления, но полный комитет WG21/PL22.16 проголосовал за применение предлагаемой резолюции о дефекте в рабочем документе.
Смотрите здесь lwg для получения дополнительной информации: http://wg21.cmeerw.net/lwg/issue2509
Предлагаемая резолюция действительно
Для третьей формы, если is_move_constructible_v<ValueType>
истинно, а is_lvalue_reference_v<ValueType>
- false, std::move(*any_cast<remove_reference_t<ValueType>>(&operand))
, в противном случае *any_cast<remove_reference_t<ValueType>>(&operand)
И список отчетов о дефектах, перечисляющий WP: http://cplusplus.github.io/LWG/lwg-defects.html#2509
Ответ 2
Реализация std::any
, которая не требует копирования, вполне возможна. Там только одна проблема: что вы делаете, когда пользователь запрашивает копию std::any
? Одно из решений этой проблемы состоит в том, чтобы сделать std::any
только перемещение, а другое - заставить исключить конструктор копирования, если базовый тип - только для перемещения, а другой должен иметь возможность копировать базовый тип. Было выбрано третье решение.
Требования к ValueType
, являющиеся копируемыми конструкциями, совершенно прекрасны - поскольку тип, который не копирует конструкцию, не может быть сохранен в экземпляре std::any
, std::any_cast
может также сделать всегда неудачный листинг a ошибка компилятора.
Теперь тот факт, что реализация ValueType any_cast(any&& operand)
не позволяет перемещаться, кажется, является надзором - в конце концов, копия - прекрасная реализация перемещения, и реализация может свободно делегировать задание на ходу конструктор, если он есть, и скопировать конструктор, если нет.