Você poderia, por exemplo, usar o padrão de design da estratégia , o Solver
sendo o contexto, Algorithm_Scheme
sendo a estratégia abstrata e Logistic_Regression_Scheme
, Linear_Regression_Scheme
estratégias concretas.
Tempo de execução?
Você pode implementar isso em tempo de execução, instanciando a estratégia correta (por exemplo, baseada no parâmetro da linha de comando) usando composição no solucionador:
class Linear_Regression_Scheme : public Algorithm_Scheme{ ...};
...
Logistic_Regression_Scheme my_scheme;
Solver my_solver(my_scheme); // constructor will keep reference or pointer to scheme
Nesse caso, você precisará incluir todos os cabeçalhos dos seus esquemas. No entanto, se o solucionador for usado em um contexto maior, e isso é realmente um problema muito sério para você, você também pode usar o idioma PIMPL, para que apenas a origem do Solver precise incluir todos os includes e os outros componentes do solver. aplicação não precisa saber sobre esses detalhes.
Ou tempo de compilação?
Mas se você tem medo de performance, você pode usar modelos para o polimorfismo em tempo de compilação. Você então instanciaria o solucionador, tendo a estratégia como argumento de modelo:
class Linear_Regression_Scheme { ...};
...
Solver<Linear_Regression_Scheme> my_solver;
Nesse cenário, você precisaria incluir apenas os cabeçalhos da estratégia concreta usada.
Observação geral
Normalmente, em C ++, o uso de macros C deve ser realmente a exceção. Normalmente é usado para compilação condicional, especialmente para incluir proteções e condições a serem definidas no processo de compilação. Mas para outros usos, pense primeiro em constantes e modelos.