2011-11-10 9 views
5

Attualmente sto esaminando un codice che può essere compilato sulle versioni più recenti di GCC ma non su quelle precedenti. Nel mio caso sto utilizzando un valore da std::back_inserter a std::copy alcuni dati da una struttura dati a una struttura dati personalizzata. Se dimentico il typedef typedef value_type & const_reference in questa struttura dati personalizzata, questo non verrà compilato su GCC 4.4. Lo stesso codice compila e gira bene su GCC 4.5.std :: back_inserter richiede const_reference su GCC precedente. Perché?

Qual è la differenza tra queste due versioni del compilatore, che rende il codice compilare su una versione, ma non dall'altra. Immagino che abbia qualcosa a che fare con l'implementazione di C++ 11, che era molto meno completa in GCC 4.4. Probabilmente qualcosa con decltype o un'altra nuova parola chiave C++ 11, direi.

Anche questo codice è corretto se si utilizza std::back_inserter senza definire il tipo const_reference? Di solito pensavo che fosse necessario implementare l'intero set di typedef (value_type, reference, const_reference ecc.) Per essere compatibile con la libreria degli algoritmi STL? O posso tranquillamente supporre che se il mio codice viene compilato in questo caso non sto invocando nulla di pericoloso (ad esempio spostare la semantica, che distruggerebbe l'altra mia struttura dati).

+0

Per la cronaca (per aiutare i principianti come me risparmiare tempo): Dopo che ho aggiunto 'typedef T & riferimento; typedef const T & const_reference; ' nella mia struttura dati, l'errore c2039 per back_inserter è scomparso. –

risposta

6

Lo standard (1998) dice che std::back_insert_iterator esigenze Container::const_reference. In "24.4.2.1 modello di classe back_insert_iterator", [lib.back.insert.iterator], si dice:

back_insert_iterator<Container>& 
operator=(typename Container::const_reference value); 

Lo standard 2011 vuole solo Container::value_type,

back_insert_iterator<Container>& 
operator=(const typename Container::value_type& value); 
back_insert_iterator<Container>& 
operator=(typename Container::value_type&& value); 

Quindi, per essere compatibile con entrambe le versioni dello standard C++ definiscono sia value_type sia const_reference_type.

In entrambi GCC 4.4.6 e 4.5.1, la definizione di operator= è identico (libstdc++-v3/include/bits/stl_iterator.h):

back_insert_iterator& 
    operator=(typename _Container::const_reference __value) 
    { 
    container->push_back(__value); 
    return *this; 
    } 

e ottengo lo stesso errore con entrambi i compilatori, forse avrete bisogno di doppio controllo se stai usando le versioni corrette del compilatore.

+0

Grazie per il chiarimento. Su 4.5.2 funziona senza il tipo const_reference, come ho appena verificato. 4.4.4 ne ha ancora bisogno. – LiKao

+1

@LiKao, negli ultimi GCC, la compatibilità della libreria C++ 0x è abilitata per impostazione predefinita. GCC4.5.2 è leggermente * più * compatibile :) di GCC 4.4 in quanto usa 'const_reference' solo quando la compatibilità è disabilitata, mentre 4.4 lo usa incondizionatamente. – chill

+0

@chill: Citando [la documentazione della versione corrente di gcc] (http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Standards.html#Standards): 'L'impostazione predefinita, se non esiste la lingua C++ le opzioni dialettali sono fornite, è -std = gnu ++ 98.. Quindi, sei sicuro di quello che dici? –

1

La ragione per cui è necessario const_reference definito per i dati-struttura è perché l'operatore di assegnazione in GCC 4.4 per un tipo di argomento lvalue nella classe std::back_insert_iterator è definita come:

template<class Container> 
back_insert_iterator<Container>& 
back_insert_iterator<Container>::operator= 
        (typename Container::const_reference value); 

Così const_reference bisogno di essere un identificatore risolvibile nel tipo di classe in per istanziare correttamente l'operatore di assegnazione nel modello di classe std::back_insert_iterator.

In GCC 4.5, questa definizione di operatore di assegnazione per argomenti lvalue è stata cambiata in

template<class Container> 
back_insert_iterator<Container>& 
back_insert_iterator<Container>::operator= 
       (const typename Container::value_type& value); 

al fine di sostenere il nuovo C++ specifica 11. Dal momento che il codice viene compilato correttamente con GCC 4.5, suppongo che devi avere value_type correttamente definito per la tua struttura dati.

Problemi correlati