CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Apr 2010
    Posts
    19

    [RESOLVED] Smart Accessor Function for Multiple Data Containers?

    Hi everyone,

    I’m Pete, moderately-experienced C++ user who is always looking for better ways to do things.

    Let me ask you guys about a problem I’ve scratching my head over lately. Suppose I’m writing a program designed to simulate a large company. I’m interested in tracking each company employee by the location where they work. This company has perhaps a thousand different locations:

    -----------------------------------------------------------------------------------------
    class Employee {
    public:
    AccessorFunction1(); // does something
    AccessorFunction2(); // does something different
    AccessorFunction3(); // does something completely different
    protected:
    // Some data
    };


    class Company {
    public:
    void OrganizeLocation(int a);

    protected:
    vector<Employee*> LocationA;
    vector<Employee*> LocationB;
    vector<Employee*> LocationC;
    ...etc...
    vector<Employee*> LocationZZZ;
    };
    -----------------------------------------------------------------------------------------

    Once employees are created and pointers to them are saved in the proper Location vector, I write an accessor function, OrganizeLocation(), designed to do a number of operations on a given vector. The problem is, I have maybe a thousand vectors. How do I call this function and specify which vector I want?

    Currently, I’m using this clunky solution:

    -----------------------------------------------------------------------------------------
    void Company::OrganizeLocation(int a){
    switch(a) {
    case 1: {
    for(unsigned int i=0; i<LocationA.size(); i++) {
    LocationA[i]->AccessorFunction1();
    LocationA[i]->AccessorFunction2();
    LocationA[i]->AccessorFunction3();
    }
    break;
    }
    case 2: {
    for(unsigned int i=0; i<LocationB.size(); i++) {
    LocationB[i]->AccessorFunction1();
    LocationB[i]->AccessorFunction2();
    LocationB[i]->AccessorFunction3();
    }
    break;
    }
    case 3: {
    // etc...
    }
    case 4: {
    // etc...
    }

    ...etc...

    case 1000: {
    // etc...
    }
    }
    }
    -----------------------------------------------------------------------------------------

    The key point here is that whichever vector I choose to operate upon, I’ll do the exact same procedure every time. I hate this solution because it results in very long and repetitive code… not to mention its very error-prone when you re-editing all those “LocationA”s into “LocationB/C/D/etc.”

    What would be an ideal solution would be if I could do some kind of string substitution into the vector name like (I think) you can do in PERL scripts:

    -----------------------------------------------------------------------------------------
    void Company::OrganizeLocation( string $WhichOne$ ){
    for(unsigned int i=0; i<LocationA.size(); i++) {
    Location$WhichOne$[i]->AccessorFunction1();
    Location$WhichOne$[i]->AccessorFunction2();
    Location$WhichOne$[i]->AccessorFunction3();
    }
    -----------------------------------------------------------------------------------------

    Does anyone know of a way to do this? Or, if it can’t be done in C++, is there a better design approach? Ultimately I need the Company object to hold multiple vectors but use one compact accessor function to perform operations on just one of them.

    Many thanks!
    -Pete

  2. #2
    Lindley is offline Elite Member Power Poster
    Join Date
    Oct 2007
    Location
    Seattle, WA
    Posts
    10,895

    Re: Smart Accessor Function for Multiple Data Containers?

    If you are satisfied identifying a location by an index, then you could store a vector<vector<Employee*>>. (Although, if I were you, I would avoid the raw pointer. Either store Employee objects directly or use smart pointers.)

    Alternatively if you'd like to identify locations by a string as shown above, perhaps a map<string, vector<Employee*>> would be preferable.

  3. #3
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Smart Accessor Function for Multiple Data Containers?

    Quote Originally Posted by phummon View Post
    Does anyone know of a way to do this? Or, if it can’t be done in C++, is there a better design approach? Ultimately I need the Company object to hold multiple vectors but use one compact accessor function to perform operations on just one of them.
    You are already using the solution to your problem, namely std::vector, or in general container classes. Whenever you start copy-pasting code, you should realize that you are doing something wrong and look for the better solution. In this case you could use a vector to have indexed access to each location, or a map if you want to access locations by name.
    Code:
    class Company {
    //...
    private
        std::vector<std::vector<Employee*> > m_Locations;
        // or
        std::map<std::string, std::vector<Employee*> > m_LocationsByName;
    };
    If your compiler supports it, you can use the faster std::unordered_map (or std::tr1::unordered_map) instead of the map, if you don't care about the order in which the locations are stored in the container.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Smart Accessor Function for Multiple Data Containers?

    Quote Originally Posted by phummon View Post
    Hi everyone,

    I’m Pete, moderately-experienced C++ user who is always looking for better ways to do things.
    If you see yourself repeating things like this:
    Code:
    vector<Employee*> LocationA;
    vector<Employee*> LocationB;
    vector<Employee*> LocationC;
    How is that any different than doing this:
    Code:
    int LocationA;
    int LocationB;
    int LocationC;
    //...
    int LocationZZZ;
    The only difference is the type -- the first is vector<Employee*> and the example I gave is int. So the obvious solution is to declare an array, or better yet a vector.
    Code:
    #include <vector>
    class Employee
    {
    //...
    };
    
    typedef std::vector<Employee*> EmployeeVector;
    typedef std::vector<EmployeeVector> AllEmployees;
    
    class Company {
      public:
        void OrganizeLocation(size_t whichOne);
    
      protected:
        AllEmployees  m_Locations;
      public:
         Company(size_t numEmployees) : m_Locations(numEmployees) { }
      };
    
    //...
    void Company::OrganizeLocation( size_t whichOne )
    {
       for( size_t i=0; i<Location[whichOne].size(); i++) 
      {
           Location[whichOne][i]->AccessorFunction1();
           Location[whichOne][i]->AccessorFunction2();
           Location[whichOne][i]->AccessorFunction3();
      }
    }
    All of that code you wrote could have been easily aggregated as above.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; March 14th, 2012 at 05:43 PM.

  5. #5
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Smart Accessor Function for Multiple Data Containers?

    Quote Originally Posted by phummon View Post
    Code:
        vector<Employee*> LocationA;
    I would also suggest you rethink why you need to store pointers to Employee rather than Employee objects.

    With the code you posted, there are no virtual functions in the Employee class, so deriving from Employee would be ill-advised anyway. So what's the reason for vector<Employee*> instead of vector<Employee>?

    Regards,

    Paul McKenzie

  6. #6
    Join Date
    Apr 2010
    Posts
    19

    Re: Smart Accessor Function for Multiple Data Containers?

    Good advice, good brain food. Much obliged!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured