C++ union array and vars?

前端 未结 8 1600
日久生厌
日久生厌 2021-02-19 22:18

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

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

Where x == v[0]<

相关标签:
8条回答
  • 2021-02-19 22:31

    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.

    0 讨论(0)
  • 2021-02-19 22:38

    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

    0 讨论(0)
  • 2021-02-19 22:38

    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.

    0 讨论(0)
  • 2021-02-19 22:41

    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;
    }
    
    0 讨论(0)
  • 2021-02-19 22:42

    Given your example:

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

    As others have noted, in general, the standard does not guarantee that there will be no padding between x and y, and actually compilers inserting padding in structures is pretty common behavior.

    On the other hand, with solutions like:

    struct U
    {
        int   v[2];
        int&  x;
        int&  y;
    };
    
    U::U()
        : x(v[0])
        , y(v[1])
    {}
    

    what I don't like mainly is the fact that I have to mention x, y twice. For cases where I have more than just a few elements (say 10), this becomes much less readable and harder to maintain. Additionally U can no longer be a POD since it needs a user-defined constructor. And finally, the x & y references consume additional memory.

    Hence, the (acceptable for me) compromise I've come up with is:

    struct Point
    {
        enum CoordType
        {
            X,
            Y,
            COUNT
        };
    
        int coords[CoordType::COUNT];
    };
    
    typedef Point::CoordType PtCoord;
    

    With this you can then do:

    Point p;
    for ( int i = 0; i < PtCoord::COUNT; i++ )
        p.coords[i] = 100;
    std::cout << p.coords[PtCoord::X] << " " << p.coords[PtCoord::Y] << std::endl;
    
    // 100 100
    

    A bit sophisticated but I prefer this over the references suggestion.

    0 讨论(0)
  • 2021-02-19 22:50

    I was looking for a similair thing and eventually came up with a solution.

    I was looking to have a data storage object that I could use as both an array of values and as individual values (for end-user flexibility in writing Arduino libraries).

    Here is what I came up with:

    class data{
        float _array[3];
    
        public:
        float& X = _array[0];
        float& Y = _array[1];
        float& Z = _array[2];
    
        float& operator[](int index){
            if (index >= 3) return _array[0]; //Make this action whatever you want...
            return _array[index];
        }
        float* operator&(){return _array;}
    };
    
    
    int main(){
        data Test_Vector;
        Test_Vector[0] = 1.23; Test_Vector[1] = 2.34; Test_Vector[2] = 3.45;
    
        cout<<"Member X = "<<Test_Vector.X;
        cout<<"Member Y = "<<Test_Vector.Y;
        cout<<"Member Z = "<<Test_Vector.Z;
    
        float* vector_array = &Test_Vector;
    
        cout<<"Array = {"<<vector_array[0]<<", "<<vector_array[1]<<", "<<vector_array[2]<<"}";
    }
    

    Thanks to Operator overloading, we can use the data object as if was an array and we can use it for pass-by-reference in function calls (just like an array)!

    If someone with More C++ experience has a better way of applying this end product, I would love to see it!

    EDIT: Changed up the code to be more cross-platform friendly

    0 讨论(0)
提交回复
热议问题