2011-11-10 25 views
5

Actualmente estoy buscando algún código que pueda compilarse en versiones más nuevas de GCC pero no en versiones anteriores. En mi caso, estoy usando std::back_inserter a std::copy algunos datos de una estructura de datos a una estructura de datos personalizada. Sin embargo, si olvido el typedef typedef value_type & const_reference en esta estructura de datos personalizada, esto no se compilará en GCC 4.4. El mismo código se compila y funciona perfectamente en GCC 4.5.std :: back_inserter necesita const_reference en GCC anterior. ¿Por qué?

Cuál es la diferencia entre estas dos versiones del compilador, que hace que el código se compile en una versión pero no en la otra. Supongo que tiene algo que ver con la implementación de C++ 11, que fue mucho menos completa en GCC 4.4. Probablemente algo con decltype u otra nueva palabra clave C++ 11, supongo.

También este código es correcto, si uso el std::back_inserter sin definir el tipo const_reference? Por lo general, pensé que uno tiene que implementar el conjunto completo de typedefs (value_type, reference, const_reference, etc.) para ser compatible con la biblioteca de algoritmos STL. ¿O puedo asumir con seguridad que si mi código se compila en este caso, no estoy invocando nada peligroso (por ejemplo, mover la semántica, lo que destruiría mi otra estructura de datos).

+0

Para el registro (para ayudar a los principiantes como yo a ahorrar tiempo): Después de agregar 'typedef T & reference; typedef const T & const_reference; ' a mi estructura de datos, el error c2039 para back_inserter ha desaparecido. –

Respuesta

6

La norma (1998) dice que std::back_insert_iterator necesita Container::const_reference. En "back_insert_iterator clase 24.4.2.1 Plantilla", [lib.back.insert.iterator], que dice:

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

La norma 2011 sólo quiere Container::value_type,

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

Por lo tanto, para que sea compatible con Ambas versiones del estándar C++ definen tanto value_type como const_reference_type.

En tanto GCC 4.4.6 y 4.5.1, la definición de operator= es idéntico (libstdc++-v3/include/bits/stl_iterator.h):

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

y me sale el mismo error con los compiladores, tal vez tendrá que comprobarlo si está utilizando las versiones correctas del compilador.

+0

Gracias por la aclaración. En 4.5.2 funciona sin el tipo const_reference, como acabo de verificar. 4.4.4 todavía lo necesita. – LiKao

+1

@LiKao, en las GCC recientes, la compatibilidad de la biblioteca C++ 0x está habilitada de manera predeterminada. GCC4.5.2 es ligeramente * más * compatible :) que GCC 4.4 en que utiliza 'const_reference' solo cuando la compatibilidad está deshabilitada, mientras que 4.4 la usa incondicionalmente. – chill

+0

@chill: Citando [la documentación de la versión actual de gcc] (http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Standards.html#Standards): 'El idioma predeterminado, si no hay C++ se dan opciones de dialecto, es -std = gnu ++ 98'. Entonces, ¿estás seguro de lo que dices? –

1

La razón por la que es necesario const_reference definido para su estructura de datos es debido a que el operador de asignación en GCC 4.4 para un tipo de argumento valor-I en la clase std::back_insert_iterator se define como:

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

Así const_reference necesario que haya una identificador resoluble de su tipo de clase para instanciar correctamente el operador de asignación en la plantilla de clase std::back_insert_iterator.

En GCC 4.5, esta definición del operador de asignación para los argumentos lvalue se ha cambiado a

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

el fin de apoyar especificación el nuevo C++ 11. Dado que su código se compila correctamente con GCC 4.5, asumo que debe tener value_type correctamente definido para su estructura de datos.

Cuestiones relacionadas