Dato GMan's deliziosamente malvagio auto_cast
funzione di utilità inventata here, Ho cercato di capire perché non viene compilato per me quando sto provando a auto_cast
da un valore di rvalue (su MSVC 10.0).C++ 0x valore di riferimento argomento argomento deduzione
Ecco il codice che sto usando:
template <typename T>
class auto_cast_wrapper : boost::noncopyable
{
public:
template <typename R>
friend auto_cast_wrapper<R> auto_cast(R&& pX);
template <typename U>
operator U() const
{
return static_cast<U>(std::forward<T>(mX));
}
private:
//error C2440: 'initializing': cannot convert from 'float' to 'float &&'
auto_cast_wrapper(T&& pX) : mX(pX) { }
T&& mX;
};
template <typename R>
auto_cast_wrapper<R> auto_cast(R&& pX)
{
return auto_cast_wrapper<R>(std::forward<R>(pX));
}
int main()
{
int c = auto_cast(5.0f); // from an rvalue
}
Al meglio delle mie possibilità ho cercato di seguire il riferimento C++ 0x collasso regole e le regole di deduzione modello di argomenti delineati here, e per quanto posso dire il codice di cui sopra dovrebbe funzionare.
Ricordiamo che in pre-0x C++, non è consentito di prendere un riferimento a un riferimento: qualcosa come un & & causa un errore di compilazione. C++ 0x, invece, presenta le seguenti regole collasso riferimento:
- Un & & diventa un &
- Un & & & diventa un &
- Un & & & diventa un &
- A & & & & diventa un & &
La seconda regola è una speciale regola detrazione modello argomento per i modelli funzionali che accettano un argomento con riferimento rvalue ad un argomento di un template:
template<typename T> void foo(T&&);
Qui, si applicano le seguenti regole :
- Quando foo è chiamato su un lvalue di tipo a, allora T risolve in un & e quindi del RIFERIME nce comprime le regole sopra, il tipo di argomento diventa effettivamente A &.
- Quando foo viene chiamato su un valore rvalore di tipo A, quindi T si risolve in A, quindi il tipo di argomento diventa A & &.
Ora, quando il mouse sopra la chiamata a auto_cast(5.0f)
, il tooltip visualizza correttamente il suo valore di ritorno come auto_cast_wrapper<float>
. Questo senso che il compilatore ha seguito correttamente Regola 2:
Quando foo è chiamata su un rvalue di tipo A, allora T decide di A.
Quindi, dal momento che abbiamo un auto_cast_wrapper<float>
, il costruttore dovrebbe istanziare per prendere un float&&
. Ma il messaggio di errore sembra implicare che esso istanzia per prendere un valore float
.
Ecco il messaggio di errore completo, che mostra ancora una volta che T = galleggiano correttamente ancora il T & & parametro diventa T?
main.cpp(17): error C2440: 'initializing' : cannot convert from 'float' to 'float &&' You cannot bind an lvalue to an rvalue reference main.cpp(17) : while compiling class template member function 'auto_cast_wrapper<T>::auto_cast_wrapper(T &&)' with [ T=float ] main.cpp(33) : see reference to class template instantiation 'auto_cast_wrapper<T>' being compiled with [ T=float ]
Qualche idea?
Qualche possibilità di mettere a fuoco la domanda un po '? Invece di mettere le modifiche in fondo come paragrafi separati, modificale * nella * domanda stessa. Come lettore non ho bisogno di sapere l'ordine in cui hai aggiunto alla domanda, voglio solo leggere la migliore versione possibile della domanda. E se vuoi pubblicare la risposta da solo, fallo come una risposta reale, non come un altro paragrafo in fondo alla domanda. Così com'è, è solo una quantità spaventosa di testo e codice che devo attraversare se voglio anche sapere di che cosa si tratta. – jalf
@jalf: Sì, mi dispiace jalf. Non volevo creare una risposta separata perché DeadMG ha già risposto correttamente. Immagino di aver pensato che sarebbe stato maleducato da parte mia farlo, anche se ho pensato che alcuni chiarimenti non sarebbero stati dannosi per chiunque altro leggesse questo in futuro. E la domanda bonus dovrebbe essere probabilmente una domanda completamente separata, in quanto non è realmente correlata all'originale. – dvide
Su SO non c'è niente di sbagliato nel postare nuove risposte migliori a domande a cui è già stata data una risposta. E se ti senti in colpa, accetta la risposta di DeadMG, ma inserisci il tuo sotto. :) – jalf