2010-05-19 26 views
27

Tengo una variable miembro de tipo vector<T> (donde está T es una clase personalizada, pero podría ser int también.) Tengo una función de la que quiero devolver un puntero a este vector, pero no quiero que la persona que llama pueda cambiar el vector o sus elementos. Así que quiero que el tipo de devolución sea const vector<const T>*moldeada vector <T> al vector <const T>

Ninguno de los métodos de conversión que probé funcionaron. El compilador sigue quejándose de que T no es compatible con const T.

Aquí hay un código que demuestra la esencia de lo que estoy tratando de hacer;

vector<int> a; 
const vector<const int>* b = (const vector<const int>*) (&a); 

Este código no compila para mí.

¡Gracias de antemano!

+1

¿por qué no devolver la referencia const? – Anycorn

+0

[vector-and-const] (http: // stackoverflow.com/questions/2102244/vector-and-const) –

Respuesta

27

Si tiene un const vector<int> no puede modificar el contenedor, ni puede modificar ninguno de los elementos del contenedor. No necesita un const vector<const int> para lograr esa semántica.

+0

Debería haberlo probado antes de preguntar. Lo probé ahora, y funciona como usted lo describió. Gracias. – user345386

+2

, pero ¿y si tengo vector ? Tiene sentido la mayor parte del tiempo para crear dichos vectores. – user3111311

2

puede forzar la conversión de esta manera:

b = reinterpret_cast<const std::vector<const int>*>(&a); 

pero no creo que usted debe hacer esto, ya que no se garantiza que funcione, sólo para compilar

+2

Dado que el OP utilizó un molde de estilo c, esto es realmente lo que intentaron hacer. Un elenco de estilo c realizará un reinterpreteo cuando los tipos no estén relacionados y el vector no esté relacionado con el vector o cualquier otra cosa. –

14

Además de la respuesta de James sobre cómo para hacerlo, debe tener en cuenta que const int no es un tipo válido para poner en ningún contenedor estándar ya que no es asignable.

12

Por qué una vector<T> no puede ser convertido correctamente a un vector<const T> incluso si T se puede convertir en const T

Este es un problema recurrente común en la programación si se trata con constness o herencia (un contenedor de objeto derivado no puede ser convertido a un contenedor de objetos base, incluso si los elementos contenidos pueden). El problema es que elemento por elemento cada uno de ellos se puede convertir, pero el contenedor no puede hacerlo sin romper el sistema de tipos.

Si se le permitiera hacer vector< const T > &vr = my_vector_of_T, entonces podría agregar elementos a través de vr, y esos elementos serían constantes por definición. Pero al mismo tiempo, esos mismos elementos se aliasen en my_vector_of_T como elementos no const y podrían modificarse a través de esa interfaz, rompiendo constness en el sistema de tipos.

En el caso particular de un vector<int> están convirtiendo en un vector<const int>, lo más probable es que no se daría cuenta de efectos realmente extraños --besides añadir un elemento a un vector<const int> y ver cómo las constantes elemento cambia en el tiempo, pero aún recuerde que dados dos tipos relacionados T1 y T2 para los cuales existe una relación, en la mayoría de los casos tratando de aplicar la misma relación a los contenedores de T1 y T2 se romperá el sistema de tipos.

+0

+1 para explicar por qué la alteración del contenedor puede causar problemas incluso si las referencias en el contenedor son const. –

0

El compilador decide bloquear esto. Sin embargo, sabemos que esto es seguro así que tal vez podamos engañarlo:

const vector<const int>* b = (const vector<const int>*)(void *)(&a); 
+3

Bueno, no es seguro. El tipo 'std :: vector ' no es válido porque 'std :: vector ' requiere que T sea asignable y 'const int' no lo es. – MSalters

+0

Lo curioso es que utilicé un compilador que compilaría esto hasta que trataras de escribir en el vector, entonces obtienes un error de compilador realmente oscuro. – Joshua

+0

"sabemos que esto es seguro" - jaja, ¡guau! "seguro" nunca es, ni una sola vez, algo apropiado para decir sobre "reinterpretar_cast" a nada excepto a '[un/signed] char const *'. Todo lo demás está definido en la implementación si tiene suerte y está dispuesto a escribir código frágil no portátil. Además, (A) 'T const' no es un tipo de elemento válido, y (B) incluso si lo fuera, el Standard no necesita poner las 2 variables de miembro de las instancias en el mismo orden, por lo que incluso si' reinterpret_cast' reinterpretó el objeto representación en su compilador, es una locura suponer que los miembros compatibles viven en compensaciones equivalentes dentro de ambos –

Cuestiones relacionadas