tags:

views:

1154

answers:

5

There's no way to do something like this, in C++ is there?

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

Where x == v[0] and y == v[1]?

+1  A: 

Depending on what "Scalar" is, yes, you can do that in C++. The syntax is almost exactly (maybe even exactly exactly, but I'm rusty on unions) what you wrote in your example. It's the same as C, except there are restrictions on the types that can be in the unions (IIRC they must have a default constructor). Here's the relevant Wikipedia article.

rmeador
Scalar is just a float or double... changeable if I need more precision. Thanks
Mark
+9  A: 

How about

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

edit:

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

Ugly, but that's more accurate

MGoDave
Of course! A struct! Brilliant!
Mark
Wouldn't you give the struct a name so you can reference union_name.struct_name.x?
Tom Ritter
I'd collapse your "b bee" line such that you end up with "struct b { ... } bee;"
rmeador
You don't need to name the union ('b'), only the member ('bee').
David Rodríguez - dribeas
Depending on what type x, y, and z are, and which specific compiler you're using, and even what the target platform is, you may see issues caused by data alignment. Essentially, x and y may not necessarily reside in memory in direct correspondence with v[0] and v[1].
John Watts
John, to fix that could you pack the structure (again compiler and platform dependent)?
MGoDave
I don't see the point of naming the struct... that just adds an extra unwanted layer of encapsulation.
Mark
+1 John Watts. C++ guarantees that elements of an array are laid out contiguously, but only guarantees that the address of an element of a POD struct is greater than the address of all earlier-declared elements (i.e. there is more flexibility in laying out structs).
j_random_hacker
At least, please add a compile-time assertion that offsetof(v[1]) == offsetof(y) (using e.g. BOOST_STATIC_ASSERT). This will be the case on most compilers/platforms, but it never hurts to make sure.
j_random_hacker
+10  A: 

Since you are using C++ and not C, and since they are of the same types, why not just make x a reference to v[0] and y a reference to v[1]

Brian R. Bondy
+1. This nicely gets around the fact that v[1] is not guaranteed by C++ language rules to correspond to y.
j_random_hacker
Assuming you mean for the code operating on the struct to declare these references as local variables: the compiler will optimise them away, so there's no need to t worry about performance.
j_random_hacker
+2  A: 

Try this:

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;
}
Martin York
g++ gives sizeof(U1<char>) as 12.. rather than 2. (g++ 4.0.1)
Michael Anderson
@Michael: Why do you think it should be 2?
Martin York
I'm saying that for something that is essentially providing access to two pieces of data, the resulting struct is expanded by a large degree by holding two additional pointers... That may be acceptable in some cases, and unacceptable in others .. Just a warning to those looking at this solution.
Michael Anderson
+1  A: 

I've used something like this before. I'm not sure its 100% OK by the standard, but it seems to be OK with any compilers I've needed to use it on.

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

You can add bounds checking etc to operator[] if you want ( you probably should want) and you can provide a const version of operator[] too.

Michael Anderson