2016-04-18 7 views
20

Sono perplesso: dopo aver eseguito l'aggiornamento a GCC 6 (RC1), alcuni codice modello utilizzavano std::common_type che funzionava prima che non funzionasse. Ho provato su clang, e anche questo fallisce ... quindi devo fare qualcosa di sbagliato!std :: common_type con riferimenti a type_info

Il codice pari a:

#include <type_traits> 
#include <typeinfo> 

using namespace std; 

// common_type of two const type_info& is ok (compiles ok) 
common_type<const type_info&, const type_info&>::type func1(); 

// common_type of three type_info& is bad...(fails to compile) 
common_type<const type_info&, const type_info&, const type_info&>::type func2(); 

// common_type of two const int& is ok 
common_type<const int&, const int&>::type func3(); 

// common_type of three const int& is ok too! 
common_type<const int&, const int&, const int&>::type func4(); 

Il secondo common_type con tre parametri di tipo std::type_info const & fallisce la compilazione. clang suggerisce suggerentemente che uso un due argomenti std::common_type, ma questo è in un modello di espansione in cui non posso controllare gli input!

Questo sembra molto strano: perché il caso const type_info& con 3 non riesce, ma nessuno dell'altro tipo apparentemente equivalente fallisce?

vedere qui: https://godbolt.org/g/Ob4y0x

+3

'common_type' ora decade e questo si traduce in cose" divertenti ". –

+0

Alcuni riferimenti a Twitter mi indicano che 'std :: common_type' restituisce' std :: decay' del Ts ... che è super fastidioso per il mio caso d'uso ma spiega gli errori sopra. –

+0

@MattG: È sempre possibile sostituire 'common_type_t ' da common_type_t ...> ', quindi non dovrebbe essere super fastidioso. –

risposta

15

In primo luogo, è common_type_t<T1, T2> (approssimativamente) std::decay_t<decltype(true? std::declval<T1>() : std::declval<T2>())>. Decompone il tipo - elimina la referenza, rimuove la qualifica cv di livello superiore e esegue la conversione da matrice a puntatore e da funzione a puntatore.

Quindi, common_type<const type_info&, const type_info&>::type è type_info. Mentre la dichiarazione di func1 sembra funzionare, avrai seri problemi a scrivere la sua definizione.

common_type_t<T1, T2, T3> è common_type_t<common_type_t<T1, T2>, T3>, quindi common_type<const type_info&, const type_info&, const type_info&>::type è common_type<type_info, const type_info&>::type.

che si traduce in un misto-valore-categoria espressione ternario, che dalle norme in [expr.cond] cercherà di fare una temporanea type_info fuori dalla operando scelte - che non funziona perché type_info 's costruttore di copia è cancellato.

In implementazioni compatibili con SFINAE, che risulta in common_type<const type_info&, const type_info&, const type_info&> senza alcun membro type. Se si utilizza un'implementazione non compatibile con SFINAE, si otterrà invece un errore grave.

+0

Grazie, questo sicuramente risponde alla domanda. Qualche idea sul perché questo è cambiato per C++ 14? Sembra che manchi qualcosa se il mio codice ha funzionato prima ma non ora :) –

+5

http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2141 –

+2

@MattG^che (in poche parole, in modo che 'common_type_t ' non sia 'int &&'). –