2016-01-20 18 views
14
class A{ 
public: 
    virtual ~A() {}; 
}; 

class B : public A{ }; 

int main(){ 

    A&& p = B(); 

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

} 

genera l'errore (g ++ 5.2.0):dynamic_cast e riferimento rvalue

error: conversion to non-const reference type 'std::remove_reference<A&>::type& {aka class A&}' from rvalue of type 'A' [-fpermissive] 

Si tenta di lanciare std::move(p) digitare A&, ma non riesco a capire perché. Avrei pensato che fosse necessario convertire p come valore di rvalue prima di convertirlo in un riferimento di rvalue, ma se rimuovo lo std::move lo compilo bene. Da cppreference:

dynamic_cast <new_type> (expression)

simili altre espressioni del cast, il risultato è:

un lvalue se new_type è un tipo di riferimento lvalue (espressione deve essere un lvalue)

un xValue se new_type è un tipo di riferimento di rvalore (espressione può essere lvalue o rvalore)

Anche 5.2.7 di N3337:

dynamic_cast<T>(v)

Se T è un tipo di puntatore, V è un prvalue di un puntatore a completare tipo di classe, e il risultato è un prvalue di tipo T Se T è un tipo di riferimento di lvalue, v deve essere un lvalue di un tipo di classe completo e il risultato è un lvalue del tipo di cui al T. Se T è un tipo di riferimento di rvalore, v deve essere un'espressione avente un completa il tipo di classe e il risultato è un valore x del tipo indicato da T.

L'unico requisito è che io uso un tipo di classe completo, che è std::move(p), non è vero?

+1

Clang non ha avuto problemi con il codice – Cubbi

+0

Confermato con gcc 5.3. Funziona senza la chiamata 'std :: move', comunque. ;) – erip

+0

... come hai notato nella tua domanda.Dovrei leggere le domande più a fondo. – erip

risposta

6

Il codice è, ovviamente, fine:

Se T è un tipo di riferimento rvalue, v deve essere un'espressione con un tipo completo di classe , e il risultato è un xValue del tipo di cui a da T.

Presumibilmente, dynamic_cast non è stato aggiornato correttamente quando sono stati introdotti i riferimenti rvalue, e impone ancora la pre-C++ 11 regola che rvalues ​​sono tenuti solo per const riferimenti lvalue (notare che non ha nemmeno il lavoro quando si modifica il tipo di destinazione su B const&&, nonostante ciò sia implicito dal messaggio di errore!).

Archiviato come #69390.

2

Questo sembra funzionare, invece:

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

Non posso dirvi il motivo per cui il vostro è corretto.