1

I would like to eliminate duplicity of code in this problem:

class PopulationMember
{
public:
    vector<int> x_;
    vector<int> y_;
}

class Population
{
    vector<PopulationMember*> members_;

    void doComputationforX_1();  // uses the attribute x_ of all members_
    void doComputationforX_2();  
    void doComputationforX_3();

    void doComputationforY_1();  // exactly same as doComputationforX_1, but 
    void doComputationforY_2();  // uses the attribute y_ of all members_
    void doComputationforY_3();  

 EDIT: // there are also functions that use all the members_ simultaniously

    double standardDeviationInX(); // computes the standard deviation of all the x_'s
    double standardDeviationInY(); // computes the standard deviation of all the y_'s
}

The duplicity is causing me to have 6 methods instead of 3. The pairwise similarity is so striking, that I can get the implementation of doComputationforY_1 out of doComputationforX_1 by simply replacing the "x_" by "y_".

I thought about remaking the problem in this way:

class PopulationMember
{
public:
    vector<vector<int>> data_; // data[0] == x_ and data[1] == y_ 
} 

But it becomes less clear this way.

I know that a precompiler macro is a bad solution in general, but I do not see any other. My subconciousness keeps suggesting templates, but I just do not see how can I use them.

Martin Drozdik
  • 11,712
  • 12
  • 69
  • 133

2 Answers2

2

If you want to keep x_ and y_ separately in the same class PopulationMember then it's better to choose pass by value solution rather than template solution:

Define the generic method as:

void doComputationfor (vector<int> (PopulationMember::*member_));
                // pointer to data  ^^^^^^^^^^^^^^^^^^^^^^^^^^

Call it as:

doComputationfor(&PopulationMember::x_);
doComputationfor(&PopulationMember::y_);

Remember that if your doComputationfor is large enough then, imposing template method would make code duplication.
With the pointer to member method, you will avoid the code duplication with a little runtime penalty.

iammilind
  • 62,239
  • 27
  • 150
  • 297
  • 1
    Oh wow, it never occurred to me, that there is such a thing as pointer to member! Thanks! It seems that I should hit the C++ books some more :) – Martin Drozdik Mar 08 '12 at 05:05
  • @MartinDrozdik, if you are new to this concept then, for startup you can also refer [pointer to data member](http://stackoverflow.com/questions/670734/c-pointer-to-class-data-member) and [pointer to function member](http://www.parashift.com/c++-faq-lite/pointers-to-members.html) for knowing how to call them. There is lot of such info on internet. – iammilind Mar 08 '12 at 05:10
1

If the API you have specified is exactly what you want users of the class to see, then just make private methods in Population called doComputation_1( const vector<int> &v ) { do stuff on v; }

And then make the public implementations 1 line long:

public:
    void DoComputationX_1() { doComputation_1( x_ ); }
    void DoComputationY_1() { doComputation_1( y_ ); }
private:
    // drop the 'const' if you will need to modify the vector
    void doComputation_1( const vector<int> &v ) { do stuff on v; }

I don't feel like this is the right solution, but I can't piece together what your class is really trying to do in order to offer up anything more meaningful.

Joe
  • 2,859
  • 14
  • 15
  • Sorry I did not specify my question well enough. I need to make computation using all the data at once. But Thank you anyway! – Martin Drozdik Mar 08 '12 at 05:08