3

Is it possible to iterate through a struct?

For example

struct team{
   int player1;
   int player2;
   int player3;
   int player4;
   ...
   int player99; 
   int size = 99;
}

then run a for loop to set or access foo 1-4?

i guess pseudocode would look something like

for(int i = 0; i < size; i++){
    player i = (i+1); 
 }

A more simplified explanation if that doesnt make sense is I Just want to be able to go through each variable without having to hard code player1 = 1; player2 =2.

7
  • 10
    Any reason why you're not using an array/vector instead of a struct? Commented Nov 1, 2012 at 16:59
  • You can cheat, to a certain extent. In this case, with a struct composed entirely of items of the same size, you can get a pointer to an instance of the struct and treat it like an array. If the struct is more heterogenous, that won't work. If it is homogenous, like this one, why not just use a vector or array? Commented Nov 1, 2012 at 17:03
  • Well I have a lot of variables that are not related to each other that will be hard coded into a struct. And i just want to iterate through them all to set another set of data to the variables that exist in my struct Commented Nov 1, 2012 at 17:04
  • If you have such set of other data, why not just make it use same struct, so you can just assign the whole struct with one =, like in plain C? Commented Nov 1, 2012 at 17:09
  • 1
    So you actually need a map of key-value pairs...? Commented Nov 1, 2012 at 17:20

4 Answers 4

5

One way is to put the players/elements into an array:

struct Team {
    static int const size = 99;
    int players[size];
};

And then:

for(int i = 0; i < size; ++i)
    int player = players[i];
Sign up to request clarification or add additional context in comments.

Comments

2

To answer your question as you've asked it, I believe that you can use the pre-compiler macro Pack (the exact phrase depends on your compiler) to guarantee the structure of the memory used to create an instance of your struct. And then you technically could increment a pointer to move through it... if you're mad. That would be a very poor way to do and not at all guaranteed to work on different compilers or even different days of the week. No what you want is a data structure to do the job for you; they come with a 100% cash-back guarantee!

The most basic structure to do this with is a fixed size array, e.g:

struct team
{
    int players[99]; //an array
    int manager;
    int coach;
    string teamName;
    //etc etc
}

Then to access your players

team myTeam;
for(int i(0); i < 99; ++i)
{
    myTeam.players[i]; //do whatever
}

The limitation of an array is that you cannot change its size once it's created. So if you try

myTeam.players[99]; //accessing invalid memory - the array values are 0 - 98

More advanced

If you need a data structure that can change size after it's created, e.g you might want to add a few more players to your team at some point in the future. Then you can use a dynamic data structure such as the std::vector or the std::deque or std::list

2 Comments

//exception thrown - the array values are 0 - 98. What. This is not Java. No exception is raised when you access an array out of its bounds. It's UB.
@Cicada shame faced I was bi-lingual curious, DON'T JUDGE ME! :( (fixed)
1

I would propose to use container instead of many variables, for example you could use std::array or std::vector. This way it will be trivial to iterate, much easier to make a copy. But also it's better from design point of view: in case you decide to change the number of players it will be much easier to change the container rather than add/remove many fields

Comments

1

You can define pointer to member, like pointer to member function:

  typedef int team::*member_t;

You can have array of pointers to all your members:

  static member_t member[size];

With this approach defining member function to iterate over all members is easy:

  template <class F>
  void for_each(F f)
  {
     for (int i = 0; i < size; ++i)
       f(this->*member[i]);
  }

And with using of preprocessor macro - you can have in one place definition of all members, in other definition of pointer to members - so you will not make any mistake with changing their order. See full code:

struct team {
#define TEAM_MEMBERS(prefix,suffix) \
  prefix player1 suffix, \
  prefix player2 suffix, \
  prefix player3 suffix

  int TEAM_MEMBERS(,);
  static const int size = 3;
  typedef int team::*member_t;
  static member_t member[size];
  template <class F>
  void for_each(F f)
  {
     for (int i = 0; i < size; ++i)
       f(this->*member[i]);
  }
};
team::member_t team::member[team::size] = {
  TEAM_MEMBERS(&team::,)
};

And some test:

#include <iostream>

int main() {
  team t = { 0 };
  t.for_each([](int m) { std::cout << m << "\n"; }); // prints 0,0,0
  int n = 0;
  t.for_each([&n](int& m) { m = n++; });
  t.for_each([](int m) { std::cout << m << "\n"; }); // prints 0,1,2
  t.player2 = 7;
  t.for_each([](int m) { std::cout << m << "\n"; }); // prints 0,7,2
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.