Philipp
Philipp

Reputation: 11813

Flexible application configuration in C++

I am developing a C++ application used to simulate a real world scenario. Based on this simulation our team is going to develop, test and evaluate different algorithms working within such a real world scenrio.

We need the possibility to define several scenarios (they might differ in a few parameters, but a future scenario might also require creating objects of new classes) and the possibility to maintain a set of algorithms (which is, again, a set of parameters but also the definition which classes are to be created). Parameters are passed to the classes in the constructor.

I am wondering which is the best way to manage all the scenario and algorithm configurations. It should be easily possible to have one developer work on one scenario with "his" algorithm and another developer working on another scenario with "his" different algorithm. Still, the parameter sets might be huge and should be "sharable" (if I defined a set of parameters for a certain algorithm in Scenario A, it should be possible to use the algorithm in Scenario B without copy&paste).

It seems like there are two main ways to accomplish my task:

Now here are my questions: - What is your opinion? Did I miss important pros/cons? - did I miss a third option? - Is there a simple way to implement the config file approach that gives me enough flexibility? - How would you organize all the factory code in the seconde approach? Are there any good C++ examples for something like this out there?

Thanks a lot!

Upvotes: 5

Views: 4359

Answers (3)

Ciaran McHale
Ciaran McHale

Reputation: 2244

There is a way to do this without templates or reflection.

First, you make sure that all the classes you want to create from the configuration file have a common base class. Let's call this MyBaseClass and assume that MyClass1, MyClass2 and MyClass3 all inherit from it.

Second, you implement a factory function for each of MyClass1, MyClass2 and MyClass3. The signatures of all these factory functions must be identical. An example factory function is as follows.

MyBaseClass * create_MyClass1(Configuration & cfg)
{
  // Retrieve config variables and pass as parameters
  // to the constructor
  int age = cfg->lookupInt("age");
  std::string address = cfg->lookupString("address");
  return new MyClass1(age, address);
}

Third, you register all the factory functions in a map.

typedef MyBaseClass* (*FactoryFunc)(Configuration *); std::map<std::string, FactoryFunc> nameToFactoryFunc; nameToFactoryFunc["MyClass1"] = &create_MyClass1; nameToFactoryFunc["MyClass2"] = &create_MyClass2; nameToFactoryFunc["MyClass3"] = &create_MyClass3;

Finally, you parse the configuration file and iterate over it to find all the entries that specify the name of a class. When you find such an entry, you look up its factory function in the nameToFactoryFunc table and invoke the function to create the corresponding object.

Upvotes: 2

Philipp
Philipp

Reputation: 11813

I found this website with a nice template supporting factory which I think will be used in my code.

Upvotes: -1

Steve Townsend
Steve Townsend

Reputation: 54168

If you don't use XML, it's possible that boost::spirit could short-circuit at least some of the problems you are facing. Here's a simple example of how config data could be parsed directly into a class instance.

Upvotes: 0

Related Questions