динамическое приведение и ссылка 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 14

2 ответа:

Ваш код, конечно, прекрасен:

Если T является ссылочным типом rvalue, v будет выражением, имеющим завершите тип класса, и результатом будет xvalue указанного типа to by T.

Предположительно, dynamic_cast не был обновлен должным образом, когда были введены ссылки rvalue, и все еще применяет правило pre-C++11, что rvalues должны быть привязаны только к ссылкам const lvalue (обратите внимание, что оно даже не работает при изменении целевого типа на B const&&, несмотря на то, что это подразумевается сообщением об ошибке!).

Подано как #69390.

Это, кажется, работает вместо этого:

B&& b = std::move(dynamic_cast<B&>(p));

Не могу сказать вам, почему ваш неверный.