Imprimir valores de todos los campos en una estructura C ++

Considere una estructura simple:

struct abc { int a; char b; } 

Obtuve algún valor en una variable definida como su estructura, y ahora quiero imprimir la siguiente.

 *a = [some value] b = [some character]* 

¿Cuál es la mejor manera de lograr esto para una estructura arbitraria sin tener que escribir una función de volcado … (…) para cada una de las estructuras que encuentro?

Parece que ya encontraste la solución, pero ampliaré un poco.

Lo que está pidiendo se llama Reflection , es decir, la capacidad de un objeto para describirse a sí mismo.

La mayoría de los lenguajes implementan la reflexión gracias a los metadatos, en python, por ejemplo, las funciones y atributos de un objeto se almacenan en un elemento de diccionario.

C ++ no tiene ningún sistema de reflexión nativo a diferencia de C # o Java, lo que impide (por ejemplo) este tipo de impresión automática / serialización o deserialización.

Sin embargo, C ++ tiene un soporte de metaprogtwigción muy poderoso que nos permite (mediante el uso de plantillas) emular la reflexión (en tiempo de comstackción). Esto generalmente se hace usando Boost.Fusion , esta biblioteca está pensada para pasar del tiempo de comstackción al tiempo de ejecución.

Como muestra el ejemplo en su enlace, la macro BOOST_FUSION_ADAPT_STRUCT permite tomar una struct estándar y darle la interfaz requerida para ser tratada como Fusion.Sequence.

Otro ejemplo sería usar Fusion.Vector o Fusion.Map para almacenar los atributos de la clase y luego exponer esta secuencia a métodos de impresión / serialización / deserialización automáticos.

Sin embargo, hay una limitación en este sistema: la metaprogtwigción no encaja bien con la progtwigción OO.

 struct Base { char a; }; // Adapt struct Derived: Base { char b; }; // Adapt void print(Base const& b) { boost::fusion::for_each(b, Print()); } 

solo imprimirá el miembro de Base (aquí a ). Cuando usa polymorphism, necesita usar métodos virtual en un punto u otro 🙂

Necesitas “reflexión” para hacer esto. La reflexión no se proporciona de forma nativa en C ++, o solo para información mínima (tipo ids / nombres).

Hay bibliotecas (como CAMP ) que implementan funciones de reflexión, por lo que si REALMENTE necesita reflexión, debe usar una.

No hay uno, no en C ++. Mala suerte.

Los comstackdores C ++ no producen metadatos. Entonces no hay forma de hacer tal cosa.

Si está usando C ++ en .NET, puede usar potencialmente las cosas de System.Reflection para ver las entrañas de su estructura. Sin embargo, C ++ no administrado rara vez almacena ese tipo de metadatos sobre los objetos.

Con C ++ 17 (quizás incluso C ++ 14), y algunos hacks rusos locos, se puede hacer parcialmente. Es decir, puede imprimir los valores de los tipos en secuencia, pero no puede obtener los nombres de los campos.

La biblioteca relevante es “magic_get” de Antony Polukhin. Específicamente, ofrece un mecanismo de iteración “para cada campo”, que toma un lambda con plantillas con tipo de parámetro auto . Ejemplo:

 struct simple { int a; char b; short d; }; simple x {42, 'a', 3}; std::stringstream ss; boost::pfr::for_each_field( x, [&ss](auto&& val) { ss << val << ' '; } ); 

La respuesta migró de una pregunta relacionada / duplicada, ya que de alguna manera nadie mencionó esto aquí.

    Intereting Posts