3

As programming becomes more complex, and the need to perform operations on struct data becomes visible. Is there a conversion method for converting a struct type into an array of its members such that:

struct FooDesc Foo{
    int num_Foo;
    int num_Bar;
    int GreenFoo;
};

can be represented by:

int Bar[2];

Or better, dynamically as:

vector<int> Bar;

The goal is to convert or re-represent the data struct as an iteratable form, without the excessive use of the assignment operator.

jww
  • 97,681
  • 90
  • 411
  • 885
Rashid Ellis
  • 330
  • 3
  • 22
  • Why not hold an array in the struct? – juanchopanza Sep 18 '14 at 20:23
  • 3
    `int Bar[2]` - no. `int Bar[3]` - yes. – barak manos Sep 18 '14 at 20:25
  • @juanchopanza The actual implementation hosts an impressive number of members defining the properties of an item, to be written to a file. I'm afraid of creating a mess of unreadable data for my eyes. But I also want to be able to append "special" properties as well. – Rashid Ellis Sep 18 '14 at 20:28
  • With `vector` you will have to copy it into the vector for your "serialized" operations, and from the vector back into the structure for "normal" operations. You can cast the address of the structure into `int*`, and then use that pointer in order to perform your "serialized" operations, which will take direct effect on the structure. BTW, what do you mean by "without the excessive use of the assignment operator"? You'll have to use the same amount of assignments regardless of how you represent this structure. Your purpose here is extremely vague, to be honest. – barak manos Sep 18 '14 at 20:28
  • What if you have a struct that contains members of different types? It sounds like maybe what you're looking for is [reflection](http://en.wikipedia.org/wiki/Reflection_(computer_programming)) which isn't automatically provided in C++. You can define and implement a reflection interface if you want though. – MooseBoys Sep 18 '14 at 20:31
  • @barakmanos Would you say that that is efficient? ...or rather I can cast a struct of `int` into a `vector` Are you saying the data is delimited similarly? – Rashid Ellis Sep 18 '14 at 20:37
  • What I'm saying is, you can't really cast into a `vector`. You have to create a `vector` and copy the contents of the structure into it. Also, the suggestion in the answer given by @40two is even nicer than the one that I suggested in my previous comment (cast the address of the structure to `int*`). – barak manos Sep 18 '14 at 20:38
  • 1
    This looks more like a application of `std::tuple`, which ties in with variadic templates for compile time dynamic manipulation. You may want to add a function to convert the relevant struct into a `std::tuple`. – Jason Sep 18 '14 at 20:40

3 Answers3

6

You could use unnamed structs to make a hybrid struct where its member could be treated as an array:

struct  Foo {
  union {
    struct {
      int x;
      int y;
      int z;
    };
    struct {
      int array[3];
    };
  };
};

LIVE DEMO

Note however, that unnamed struct comes from C11 and its not a standard C++ feature. It is supported as an extension though by GCC as well Clang.

101010
  • 41,839
  • 11
  • 94
  • 168
  • The union creates a pointer to a single data location for both representations? That's extremely useful! – Rashid Ellis Sep 18 '14 at 20:45
  • The implementation worked without any problems. (VS2013) This solution opened the door for a `vector` assignment to append all the necessary data into one dynamic array. The next task is to create a design to handle structs with variable types I suppose. – Rashid Ellis Sep 18 '14 at 22:40
2

If your structs are POD then you might consider using std::tuple instead of structs. You could then use various template facilities to work through the members of the tuple.

Here is a simple example that prints the elements of a tuple - using boost::fusion::tuple instead of the std::tuple since it has many more tuple-manipulating facilities available:

#include <boost/fusion/tuple.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <iostream>

struct Printer {    
    template<typename T>
    void operator()(const T &t) const {
        std::cout << t << std::endl;
    }
};

int main(int argc, const char * argv[])
{
    boost::fusion::tuple<int, int, int, int, float> t = 
          boost::fusion::make_tuple(3, 5, 1, 9, 7.6f);

    boost::fusion::for_each(t, Printer());

    return 0;
}

You could include these in unions with the struct but you'd want to do some testing to ensure proper alignment agreement.

The upside is that these manipulations are very fast - most of the work is done at compile time. The down-side is that you can't use normal control structs like indexing with runtime indices - you'd have to build an abstraction layer around that as the normal get<i>(tuple) accessor requires that i be a compile time constant. Whether this is worth the complexity depends strongly on the application.

sfjac
  • 7,119
  • 5
  • 45
  • 69
  • I'll have to research it's implementation a bit and get back. – Rashid Ellis Sep 18 '14 at 20:49
  • What sort of things do you want to do to the members? – sfjac Sep 18 '14 at 20:54
  • Just iterate through them and write a file. I suppose that I could just output the title with the data while outputting but I also wanted to append multiple struct's data to the file- with the option of dynamically storing additional "members". Edit: boring stuff: Imagine a game character. – Rashid Ellis Sep 18 '14 at 21:35
1

How about:

vector <Foo> Bar;

You can then add instances of your struct and then access each element as desired, using an array-like format.

See this related question for further information:

Vector of structs initialization

Upon re-reading your question a few times, I think I mis-understood your intent and answered the "wrong question". You can make an array of your struct as mentioned above and index it as an array, but I don't believe it is quite as simple as that to make each struct element a different element of an array. If you are looking to make an array of structs, my answer should help. If you are looking to make each element of your struct an element of your array, 40two's answer should help you out.

Community
  • 1
  • 1
Jonathan
  • 1,050
  • 1
  • 12
  • 36