Dynamic_cast и ссылка на rvalue
class A{
public:
virtual ~A() {};
};
class B : public A{ };
int main(){
A&& p = B();
dynamic_cast<B&&>(std::move(p));
}
Выдает ошибку (g++ 5.2.0):
error: conversion to non-const reference type 'std::remove_reference<A&>::type& {aka class A&}' from rvalue of type 'A' [-fpermissive]
Он пытается использовать std::move(p)
для ввода A&
, но я не могу понять, почему. Я бы подумал, что нужно сделать p
как rvalue перед преобразованием в ссылку rvalue, но если я удалю std::move
, он компилируется отлично. Из cppreference:
dynamic_cast < new_type > ( expression )
Подобно другим выражениям, результат:
значение lvalue, если new_type является ссылочным типом lvalue (выражение должно быть lvalue)
значение xvalue, если new_type является ссылочным типом rvalue (выражение может быть lvalue или rvalue)
Даже 5.2.7 из N3337:
dynamic_cast<T>(v)
Если T является типом указателя, v должно быть prvalue указателя на полный тип класса, а результатом является prvalue типа T. Если T является ссылочным типом lvalue, v должен быть значением l полного класса type, и результатом является lvalue типа, на который ссылается T. Если T является ссылочным типом rvalue, v должно быть выражением, имеющим полный тип класса, а результатом является значение x типа, на которое ссылается Т.
Единственное требование, заключающееся в том, что я использую полный тип класса, который std::move(p)
is, не так ли?
Ответы
Ответ 1
Ваш код, конечно, прекрасен:
Если T
является ссылочным типом rvalue, v
должно быть выражением, имеющим полный тип класса, а результатом является значение x указанного типа на T
.
Предположительно, dynamic_cast
не был правильно обновлен, когда были введены ссылки rvalue, и по-прежнему применяет правило pre-С++ 11, что значения r должны быть привязаны только к const
lvalue reference (обратите внимание, что это даже не работа при изменении целевого типа на B const&&
, несмотря на то, что это подразумевается сообщением об ошибке!).
Подано как # 69390.
Ответ 2
Кажется, что это работает:
B&& b = std::move(dynamic_cast<B&>(p));
Не могу сказать, почему вы ошибаетесь.