динамическое приведение и ссылка 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-значение типа указателя на полный класс, а результат-значение типа T. Если T-ссылочный тип lvalue, то v - значение типа полного класса, а результат-значение типа lvalue, на которое ссылается T. Если T-значение типа rvalue ссылочный тип, v-выражение, имеющее полный тип класса, а результатом является xvalue типа, на который ссылается T .
std::move(p)
, не так ли?2 ответа:
Ваш код, конечно, прекрасен:
Если
T
является ссылочным типом rvalue,v
будет выражением, имеющим завершите тип класса, и результатом будет xvalue указанного типа to byT
.Предположительно,
dynamic_cast
не был обновлен должным образом, когда были введены ссылки rvalue, и все еще применяет правило pre-C++11, что rvalues должны быть привязаны только к ссылкамconst
lvalue (обратите внимание, что оно даже не работает при изменении целевого типа наB const&&
, несмотря на то, что это подразумевается сообщением об ошибке!).Подано как #69390.