Как избежать этого дубликата кода с помощью шаблонов в 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; }
Я не чувствую, что это правильное решение, но я не могу собрать воедино то, что ваш класс действительно пытается сделать, чтобы предложить что-то более значимое.