C++ iterating a struct

后端 未结 4 1701
囚心锁ツ
囚心锁ツ 2021-01-21 10:27

Is it possible to iterate through a struct?

For example

struct team{
   int player1;
   int player2;
   int player3;
   int player4;
   ...
   int player         


        
相关标签:
4条回答
  • 2021-01-21 11:04

    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];
    
    0 讨论(0)
  • 2021-01-21 11:06

    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

    0 讨论(0)
  • 2021-01-21 11:20

    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
    }
    
    0 讨论(0)
  • 2021-01-21 11:22

    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

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