Как избежать этого дубликата кода с помощью шаблонов в C++

Я хотел бы устранить двойственность кода в этой проблеме:

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
}

Двойственность заставляет меня иметь 6 методов вместо 3. Парное сходство настолько поразительно, что я могу получить реализацию doComputationforY_1 из doComputationforX_1, просто заменив "x_" на "y_".

Я думал о том, чтобы переделать проблему таким образом:

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

Но так становится менее понятно.

Я знаю, что макрос прекомпилятора - плохое решение в целом, но я не вижу другого. Мое подсознание продолжает предлагать шаблоны, но я просто не понимаю, как их использовать.

2 ответа

Решение

Если вы хотите сохранить x_ а также y_ отдельно в том же class PopulationMember тогда лучше выбрать проходное решение, чем template решение:

Определите универсальный метод как:

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

Назовите это как:

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

Помните, что если ваш doComputationfor достаточно велик, навязывая template метод сделает дублирование кода.
С указателем на метод member вы избежите дублирования кода с небольшим штрафом за время выполнения.

Если указанный вами API именно то, что вы хотите, чтобы пользователи класса видели, просто создайте в Population закрытые методы, называемые doComputation_1( const vector<int> &v ) { do stuff on v; }

А затем сделайте публичные реализации длиной в 1 строку:

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; }

Я не чувствую, что это правильное решение, но я не могу собрать воедино то, что ваш класс действительно пытается сделать, чтобы предложить что-то более значимое.

Другие вопросы по тегам