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));

Не могу сказать, почему вы ошибаетесь.