Mapeo de vectores de tipo arbitrario

Necesito almacenar una lista de vectores de diferentes tipos, cada uno para ser referenciado por un identificador de cadena. Por ahora, estoy usando std::map con std::string como la clave y boost::any como su valor (ejemplo de implementación publicado aquí).

Me despegué al intentar ejecutar un método en todos los vectores almacenados, por ejemplo:

std::map<std::string, boost::any>::iterator it;
for (it = map_.begin(); it != map_.end(); ++it) {
  it->second.reserve(100);  // FAIL: refers to boost::any not std::vector
}

Mis preguntas:

  • ¿Es posible lanzar boost::any a un tipo de vector arbitrario para poder ejecutar sus métodos?
  • ¿Hay una mejor manera de mapear vectores de tipos arbitrarios y recuperarlos más tarde con el tipo correcto?

Actualmente, estoy jugando con una implementación alternativa que reemplaza boost::any con un puntero a una clase de contenedor base como se sugiere en esta respuesta. Esto abre una nueva lata de gusanos con otros problemas que necesito resolver. Estoy feliz de seguir esta ruta si es necesario, pero todavía estoy interesado en saber si puedo hacer que funcione con boost::any, de si hay otras soluciones mejores.

PD: soy un C++ n00b novato (y he sido mimado por la escritura dinámica de Python durante demasiado tiempo), por lo que es posible que esté haciendo esto de manera incorrecta. Las críticas duras (idealmente seguidas de sugerencias) son muy bienvenidas.


El panorama:

Como se señaló en los comentarios, esto bien puede ser un problema XY, así que aquí hay una descripción general de lo que estoy tratando de lograr.

Estoy escribiendo un programador de tareas para un marco de simulación que gestiona la ejecución de tareas; cada tarea es una operación elemental sobre un conjunto de vectores de datos. Por ejemplo, si task_A se define en el modelo como una operación sobre "x"(double), "y"(double), "scale"(int) entonces lo que efectivamente estamos tratando de emular es la ejecución de task_A(double x[i], double y[i], int scale[i]) para todos los valores de i.

Cada tarea (función) opera en diferentes subconjuntos de datos, por lo que estas funciones comparten una firma de función común y solo tienen acceso a los datos a través de API específicas, por ejemplo get_int("scale") y set_double("x", 0.2).

En una encarnación anterior del marco (escrito en C), las tareas se programaban de forma estática y el marco generaba código basado en un modelo determinado para ejecutar la simulación. El orden de las tareas se basa en un gráfico de dependencia extraído de la definición del modelo.

Ahora estamos intentando crear un tiempo de ejecución común para todos los modelos con un programador de tiempo de ejecución que ejecuta tareas a medida que se cumplen sus dependencias. El paso de generar un código específico del modelo a uno genérico ha provocado todo tipo de problemas. Esencialmente, necesito poder manejar genéricamente vectores heterogéneos y acceder a ellos por "nombre" (y tal vez type_info), de ahí la pregunta anterior.

Estoy abierto a sugerencias. Cualquier sugerencia.

preguntado el 03 de mayo de 12 a las 16:05

Esto me parece un caso clásico de la Problema XY. Lo que está tratando de hacer es simplemente un ajuste muy pobre con C++. Probablemente necesite retroceder un poco y decirnos lo que realmente está tratando de lograr. Ahora mismo, sin embargo, parece (al menos para mí) que no estás escribiendo C++; estás escribiendo Python con sintaxis C++. -

estaría de acuerdo Ciertamente no puedes hacer lo que quieras con boost::any sin un montón de desagradables saltos a través de los aros para realizar un seguimiento de exactamente qué tipo de vector se almacena en cada ranura, por lo que este sería el momento de dar un paso atrás y ver todo el problema nuevamente porque es probable que esté usando el tipo de datos incorrecto. En realidad, ese suele ser el caso cada vez que any empieza a parecer una posibilidad. Tiene su lugar, pero no es uno grande. -

@JerryCoffin Yo también estoy de acuerdo. Ciertamente se siente como si estuviera yendo contra la corriente del idioma con obstáculos en cada giro que doy. Veré qué puedo hacer para describir el panorama general. Tengo miedo de convertir esto en un "este es mi problema, diseña una solución para mí" pregunta que bien puede ser demasiado complicada y probablemente fuera de tema para desbordamiento de pila. -

@JerryCoffin He agregado una descripción general de lo que estoy tratando de intentar. Espero eso ayude. (ps, me desconectaré pronto, pero abordaré todos los comentarios tan pronto como pueda) -

Parece que no necesita mantener todos los vectores en el mismo mapa. ¿Por qué no tener un mapa por tipo? -

1 Respuestas

Mirando a través de los detalles agregados, mi reacción inmediata sería separar los datos en varios mapas separados, con el tipo como parámetro de plantilla. Por ejemplo, reemplazarías get_int("scale") con get<int>("scale") y set_double("x", 0.2) con set<double>("x", 0.2);

Alternativamente, usando std::map, podría cambiar eso fácilmente (por ejemplo) a algo como doubles["x"] = 0.2; or int scale_factor = ints["scale"]; (aunque es posible que deba tener un poco de cuidado con este último: si intenta recuperar un valor inexistente, lo creará con la inicialización predeterminada en lugar de señalar un error).

De cualquier manera, terminas con una cantidad de colecciones separadas, cada una de las cuales es homogénea, en lugar de tratar de juntar varias colecciones de diferentes tipos en una gran colección.

Si realmente necesita juntarlos en una sola colección general, pensaría mucho en usar solo una estructura, por lo que se convertiría en algo como vals.doubles["x"] = 0.2; or int scale_factor = vals.ints["scale"];

Al menos de antemano, no veo que esto pierda mucho de nada, y al retener el tipeo estático en todo momento, ciertamente parece encajar mejor con la forma en que se pretende que funcione C++.

contestado el 03 de mayo de 12 a las 18:05

Probablemente debería haber agregado que 1) las API de acceso también deben estar disponibles para las funciones de C por razones heredadas, por lo tanto, se evitan los parámetros de plantilla, y 2) los tipos no se limitan a primitivos y pueden ser tipos de datos definidos por el usuario, por lo que Todavía necesitaré administrar mi colección de mapas si los mantengo homogéneos. De todos modos, consideraré sus sugerencias y lo resolveré cuando regrese a mi escritorio por la mañana. Muchas gracias por tu comentario. - barbilla shawn

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.