2011-01-24 7 views
12

Tengo una función con una firmaC++ ¿Cómo pasar una lista de los no consts a una función querer una lista de consts

void Foo(list<const A*>) 

y quiero pasar un

list<A*> 

¿Cómo hago esto? (nota de PLZ - la lista no es constante, solo el miembro de la lista)

+0

¿Intentó pasar la lista tal como es? Si es así, ¿qué obtuviste? – Oswald

+0

@Oswald, un horrible error de conversión de plantilla – vondip

+0

Algo así como 'error: conversión de 'std :: list >' a tipo no escalar 'std :: list > 'requested'? – James

Respuesta

19

El problema que tiene es que a pesar de T * se puede convertir implícitamente a un T const *, el sistema de plantillas no es "consciente" de que, por lo que un whatever<T *> y whatever<T const *> son tipos que no tienen relación, y no hay conversión implícita de una al otro.

Para evitar el problema, probablemente evitaría pasar una colección. En su lugar, haría que la función tomara un par de iteradores. Un list<A *>::iteratorpuede convertirse implícitamente en un list<A *>::const_iterator. Para el caso, probablemente haga de la función una plantilla, por lo que puede tomar iteradores de tipo arbitrario.

Es probable que esto le ahorrará un poco de problemas - una list es rara vez una buena opción de contenedor, por lo que hay una gran posibilidad de que algún día querrá cambiar de list<A *> a vector<A *> o tal vez deque<A *> - - y si hace que su función sea genérica, podrá hacerlo sin tener que volver a escribir la función.

+7

Buen consejo sobre el uso de iteradores. Sin embargo, no hay relación entre 'list :: iterator' y' list :: iterator' (o 'const_iterator'), por lo que una función que tome iteradores debe tomarlos como parámetros de plantilla. –

+1

@Oswald: probablemente un 'reinterpret_cast' funcionará en este caso tan especial. Sin embargo, no hay una solución limpia, excepto para abstraer la lista a través de iteradores. En C# 4 tiene genéricos covariantes, que resuelven este tipo de problemas con bastante elegancia (y abren la puerta a poderosas abstracciones). –

0

Puede crear una nueva lista y completarla con los valores de su lista original. Tal vez no sea la solución más eficiente en cuanto a tiempo de ejecución y la gestión de la memoria se refiere, pero ciertamente fácil de código:

list<A*> list1; 
list<const A*> list2; 
for(list<A*>::iterator a=list1.begin(); a!=list1.end(); a++) list2.push_back(*a); 
0

Vas a tener que crear una copia de la lista - es un pase por valor argumento. Hay una forma bastante sencilla de crear una copia, ya que los tipos de elemento tienen una conversión implícita: todos los contenedores STL se pueden crear a partir de un par de iteradores. Así que, en su caso:

std::list<A*> src; 
Foo(std::list<const A*>(src.begin(), src.end())); 

Esto es un poco más difícil de lo que debe ser, porque la STL representa rangos como pares de los iteradores, y reglas de conversión C++ funciona en objetos individuales.

Cuestiones relacionadas