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?
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.