2009-03-31 11 views
7

No hay forma de hacer algo como esto, en C++ está allí?C++ union array y vars?

union { 
    { 
     Scalar x, y; 
    } 
    Scalar v[2]; 
}; 

Dónde x == v[0] y y == v[1]?

+2

Tenga en cuenta que, si bien C++ garantiza que los elementos de una matriz se disponen contiguamente, solo garantiza que la dirección de un elemento de una estructura POD sea mayor que la dirección de todos los elementos declarados anteriormente. Esto significa que es posible (aunque poco probable) que v [1] y y no correspondan. –

+0

@ j_random_hacker: ¿Estás seguro? Creo que hay otra regla, heredada de C, de la que puede deducirse que no hay relleno inicial (algo en las reglas de alias IIRC, sobre el acceso a una estructura mediante un puntero del tipo del primer elemento) – MSalters

+1

Sí, esa regla existe en C++ también. No hay relleno inicial, pero creo que @j_random_hackers señala que puede haber relleno en la estructura después del primer elemento (y antes del segundo) – jalf

Respuesta

14

¿Qué tal

union { 
    struct { 
     int x; 
     int y; 
    }; 
    int v[2]; 
}; 

edición:

union a { 
    struct b { int first, second; } bee; 
    int v[2]; 
}; 

feo, pero eso es más precisa

+0

¡Por supuesto! Una estructura! ¡Brillante! – mpen

+1

¿No le daría un nombre a la estructura para que pueda hacer referencia a union_name.struct_name.x? –

+0

Colapsaré tu línea "b bee" de modo que termines con "struct b {...} bee;" – rmeador

1

Según lo que sea "Scalar", sí, puede hacerlo en C++. La sintaxis es casi exactamente (tal vez exactamente exactamente, pero estoy oxidado con los sindicatos) lo que escribiste en tu ejemplo. Es lo mismo que C, excepto que hay restricciones sobre los tipos que pueden estar en las uniones (IIRC deben tener un constructor predeterminado). Aquí está el relevante Wikipedia article.

+0

Scalar es solo un flotador o doble ... modificable si necesito más precisión. Gracias – mpen

16

Puesto que usted está usando C++ y no en C, y puesto que son del mismo tipo, ¿por qué no simplemente hacer referencia xa v [0] y ya referencia a v [1]

+2

+1. Esto supera el hecho de que v [1] no está garantizado por las reglas de lenguaje C++ para corresponder a y. –

+0

Suponiendo que quiere decir que el código que opera en la estructura declara estas referencias como variables locales: el compilador las optimizará, por lo que no hay necesidad de preocuparse por el rendimiento. –

6

Pruebe esto:

template<class T> 
struct U1 
{ 
    U1(); 
    T v[2]; 
    T& x; 
    T& y; 
}; 

template<class T> 
U1<T>::U1() 
    :x(v[0]) 
    ,y(v[1]) 
{} 

int main() 
{ 
    U1<int> data; 

    data.x = 1; 
    data.y = 2; 
} 
+1

g ++ da sizeof (U1 ) como 12 .. en lugar de 2. (g ++ 4.0.1) –

+0

@Michael: ¿Por qué crees que debería ser 2? –

+4

Estoy diciendo que para algo que esencialmente proporciona acceso a dos datos, la estructura resultante se expande en gran medida al mantener dos punteros adicionales ... Eso puede ser aceptable en algunos casos, e inaceptable en otros. Solo una advertencia para aquellos que buscan esta solución. –

4

He usado algo así antes. No estoy seguro de que esté 100% de acuerdo con el estándar, pero parece estar bien con cualquier compilador que haya necesitado para usarlo.

struct Vec2 
{ 
    float x; 
    float y; 
    float& operator[](int i) { return *(&x+i); } 
}; 

Puede agregar comprobación de límites, etc para el operador [] si quiere (que probablemente debería querer) y se puede proporcionar una versión const del operador [] también.