Referencia de nombre de coste cero amigable con el depurador para una ubicación específica en una matriz

SOURCE 5735 palabras c++c++14

Estoy buscando una solución al problem a.

struct A
{
    int a   = 1;
    short b = 2;
    char c  = 3;
}

struct B
{
    using arr_type = array<A,3>;
    char asd = 0;
    A a1;  
    A a2;
    A a3;

    // is this safe to use to loop trough all 3 elements?
    arr_type* p1 = reinterpret_cast<arr_type*>(&a1);

    // or maybe this one?
    A* p2 = &a1;
};
¿Puedo usar p1 o p2 de forma segura desde a1...a3?
B b;

for (int i = 0; i < 3; i++)
{
     cout << p1[i];
     cout << p2[i];
}
La razón por la que no es una matriz simple es que quiero que cada elemento tenga el nombre correcto.
En su lugar, puedo usar un enfoque federado, pero C++ prohíbe las estructuras anónimas (aunque no es un problem a para mí porque MSVC lo soporta, y GCC parece apoyar las estructuras anónimas);
union E
{
    A arr[3];
    struct {
        A a1;
        A a2;
        A a3;
    };
};
El siguiente código es obviamente seguro, pero cada referencia tiene una sobrecarga de 4 bytes. No me gusta. (más el costo de inicializar la referencia)
struct B
{
    char asd;
    A arr[3];  
    A& a1 = arr[0];
    A& a2 = arr[1];
    A& a3 = arr[2];
};
Este no es un gasto, pero no es lo suficientemente bueno para mi caso muy específico.
struct B
{
    char asd;
    A arr[3];  
    A& a1() { return arr[0] };
    A& a2() { return arr[1] };
    A& a3() { return arr[2] };
};
A menudo usaré estos nombres a1, a2, a3, y si son llamadas de función en Visual Studio, es más difícil depurarlos. Una vez más, usaré estos campos con frecuencia, así que espero poder comprobar fácilmente sus valores.

Esto es parte de la solución

struct B
{
     using arr_type = array<A,3>;
     char asd = 0;
     A a1;  
     A a2;
     A a3;

     // is this safe to use to loop trough all 3 elements?
     arr_type* p1 = reinterpret_cast<arr_type*>(&a1);
 };

Los tipos de estructuras y matrices necesitan ser alineados naturalmente, pero no sé ninguna regla que diga que deben ser los mismos puntos de alineación.
Si hay tal regla, los límites de diseño de la estructura y los límites de la matriz para un miembro como este serán los mismos - sólo se aplicará a las estructuras de diseño estándar:
https://stackoverflow.com/a/7189821/211160
Si haces algo así, todas las apuestas serán canceladas:
private:
    A a1;
    A a2;
public:
    A a3;
Puedo imaginar que si contiene cualquier cosa que encienda el interruptor de diseño estándar, todas las apuestas serán canceladas. Porque hay un problem a al principio, así que diría que ni siquiera lo hagas en ese momento.
(también quiero saber qué diferencia hace #pragma pack() entre matrices y estructuras... Sólo quiero saber que # pragmas no existe en el estándar.)
union E
{
    A arr[3];
    struct {
        A a1;
        A a2;
        A a3;
    };
};

No, arr[N] y aN no son iguales. Hay algunos detalles sutiles sobre cómo usar la secuencia inicial en un consorcio para una lectura compatible en C++... Pero esto es sólo entre estructuras con secuencias compatibles. No menciona estructuras ni matrices:
Type punning a struct in C and C++ via a union

I'm gonna be using those a1, a2, a3 names very often, and it's harder to debug them if they are function calls in visual studio. And again, I'm going to be using those fields a lot, so I want to be able to check their values easily.

"And the following is clearly safe, but it has a 4 byte overhead for each reference"


De hecho, parece que tienes razón, el GCC de hoy no lo está optimizando (según tu enlace):
https://godbolt.org/g/6jAtD5
http://ideone.com/zZqfor
Es decepcionante que puedan optimizarse, ya que los criterios no especifican que deben ocupar espacio. Apuntan internamente a la estructura y no cambian durante el ciclo de vida de la estructura:
Su queja sobre el acceso a la función que se optimizará es que no es lo suficientemente amigable con el depurador. ¿Por qué no hacer ambas cosas?
struct B
{
    char asd;
    A arr[3];

    A& a1() { return arr[0] }
    const A& a1() const { return arr[0]; }
    A& a2() { return arr[1] };
    const A& a2() const { return arr[1]; }
    A& a3() { return arr[2] };
    const A& a3() const { return arr[2]; }

#if !defined(NDEBUG)
    A& a1_debug = arr[0];
    A& a2_debug = arr[1];
    A& a3_debug = arr[2];
#endif
};
Si la función de proyección de la estructura de datos amigable con el depurador es importante para usted... Aprender a escribir ayuda de depurador personalizada para su entorno puede ser una buena manera de aprovechar el tiempo, por ejemplo:
http://doc.qt.io/qtcreator/creator-debugging-helpers.html
Creo que depende de cuánto tiempo tengas esa preocupación.