5

So I am creating a numerical solver that I want to use for many problems/algorithms. The way that it's written, there is a generic class called "Algorithm_Scheme" (and associated files Algorithm_Scheme.h and Algorithm_Scheme.cpp) that is included as a member of the "Solver" class.

To create an executable for a different problem/ algorithm, I replace the text "Algorithm_Scheme" with the name of specific schemes that I've created. E.g. "Logistic_Regression_Scheme", "Linear_Regression_Scheme", etc. This way I can create different executable for each problem/ algorithm. Is there a better way of doing this? Should I define a macro? So for instance:

#define Algorithm_Scheme Logistic_Regression_Scheme

in order to create the different executables? An issue is that I will have to change the #include's to only include the Algorithm_Scheme header that I want... What are your thoughts? I'm just doing the first thing that comes to my head. I don't know what best practices would be.

  • 4
    Why do you need multiple executables? Have you considered a configuration setting or command-line argument to switch between the different implementations of your Algorithm_Scheme? – Ben Cottrell Mar 4 '17 at 23:28
  • Do you mean just having 1 executable that can do every single algorithm? Won't that be inefficient? – RobertHannah89 Mar 4 '17 at 23:38
  • What I'm planning to do is just have a command-line #define command to add the correct module. – RobertHannah89 Mar 4 '17 at 23:40
  • With a define to pick one implementation and a modern linker that elides dead code, you don't need to mess around with conditionally including specific code. – user22815 Mar 4 '17 at 23:44
  • 1
    Why don't you use polymorphism instead of define macros? I think you need polymorphism, strategy pattern and dependency injection. – Q Q Mar 5 '17 at 19:24
2

You could for example use the strategy design pattern, the Solver being the context, Algorithm_Scheme being the abstract strategy, and Logistic_Regression_Scheme, Linear_Regression_Scheme concrete strategies.

Run-time ?

You can implement this at runtime, instantiating the right strategy (for example based on command line parameter) using composition in the solver:

 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

In this case, you'll need to include all the headers of your schemes. However if the solver is used in a larger context, and this is really a very serious issue for you, you could as well use the PIMPL idiom, so that only the Solver source needs to include all the includes, and the other components of the application need not to know about these details.

Or compile-time ?

But if you fear for performance, you can use templates for compile-time polymorphism. You'd then instantiate the solver, having the strategy as template argument:

 class Linear_Regression_Scheme { ...}; 
 ...
   Solver<Linear_Regression_Scheme> my_solver; 

In this scenario, you'd need to include only the headers of the concrete strategy that you use.

General remark

Normally in C++, use of C macros should really be the exception. Typically it's used for conditional compilation, especially for include guards and for conditions to be defined in the build process. But for other usages, think first of constants and templates.

  • And a foundational feature of OOP used in the Strategy Pattern is Polymorphism. This is an essential tool in a programmer's tool belt. – Greg Burghardt May 31 '17 at 23:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.