Search code examples
c++templatesboostdispatcherfactory-pattern

C++ Factory Pattern with Heterogenous Constructor Constraint


I'm implementing a C++ program that can programmatically instantiate objects given an input file which provides the class names and arguments to pass to the constructors.

The classes are derived from a common base class but their constructor signature varies.

They are declared as follows:

class Base { ... }
class Class1 : Base { Class1(int a1, int a2); }
class Class2 : Base { Class2(int a1, int a2, int a3); }
... and so on...

The argument types do not have to be int's, in fact they could be any built-in type or complex, custom type.

The program input could look like this in JSON form:

[
  { "Class1": ["arg11", "arg12"] },
  { "Class2": ["arg21", "arg22", "arg23"] },
  ...and so on...
]

Reading through the docs for Boost.Functional/Factory it appears that it could solve my problem were it not for the fact that in my application the constructor signature varies (the heterogeneity constraint). Boost.Function/Factory's approach is to normalize the constructor signatures however this is not possible in my application.

In a dynamic language like Python, this would be rather trivial: obj = klass(*args) where klass = Class1 and args = ["arg11, "arg12"].

So how would one go about implementing the factory pattern with the heterogenous constraint in C++?

Are there other libraries besides Boost that I have overlooked that may be of assistance?

Is it possible to implement this such that the only dependency is the standard library (i.e. no Boost)?

Furthermore, in the case where a constructor argument is of a complex type so that it must be specially constructed from its JSON representation, how does it affect the complexity of the problem?


Solution

  • To achieve what you want you will need, at some point in your code, a giant switch-statement to decide which class to construct based on the name (actually, a switch won't work, because you can't switch on strings - more like a very long if-else if).

    Also, it seems that the representation you show does not contain any information about the type of the constructor arguments. This could be a problem if you have a class that has multiple constructors callable with the same number of arguments.

    In the end, I think it is best if you go with something like @selbies answer, but use code-generation to generate the construction-code for you.