I have a template-heavy code at hand in which classes which are supposed to be used as template parameters to the user code, have different constructor signatures. My problem is, that I have not found a good way to call the constructors of the templated Classes in my user code. A mimimal working example could look like this:
#include <string>
#include <iostream>
#include <memory>
class ShortConstructorInLibrary {
std::string myName;
static const int tag = 1;
public:
ShortConstructorInLibrary(std::string name) :
myName(name) {
}
};
class LongConstructorInLibrary {
private:
int a;
double b;
public:
static const int tag = 2;
LongConstructorInLibrary(int arg1, double arg2) :
a(arg1), b(arg2) {
}
};
//above is library code
template<typename T>
class MyClass {
std::shared_ptr<T> member_p;
//i want to call right constructor for both cases:
public:
MyClass() {
//how do i call the different constructors properly?!
member_p = std::shared_ptr<T>(new T("test"));
}
};
int main() {
MyClass<ShortConstructorInLibrary> obj; //works
//MyClass<LongConstructorInLibrary> obj2; // wrong constructor signature
}
Here I have two classes in a library, one with a long and unrelated constructor signature, one with a short one. I want to be able to use both of them as template parameters. In my userClass I somehow have to define what arguments to pass to the constructors depending on the type passed.
I can not use a simple if() because the compiler will check both signatures and one will be wrong. I can not use c++17 for "if constexpr(){}".
I can pass the template Parameter "ShortConstructorInLibrary" to my class and call its constructor perfectly fine, but when I use the other class it will, of course, fail for a wrong constructor signature. I used an ugly trick so far that i implemented two helper methods where i pass a pointer and then let the two methods implement the constructor calls, but that seems ugly to me. I also fiddled around with std::enable_if<> but did not get very far. @Mohit proposed to use partial template specialization, but in the real world code the Short ConstructorInLibrary class is itself templated with a couple of ...templated template arguments. To give you an idea:
‘class CFEM_LOP<Dune::PDELab::QkLocalFiniteElementMap<Dune::GridView<Dune::DefaultLeafGridViewTraits<const Dune::YaspGrid<2> > >, double, double, 1ul>, EngwHillenKnapp2014<MedicalDataManager<double, Dune::YaspGrid<2> >, Dune::YaspGrid<2> >, CFEM_L2OP<Dune::PDELab::QkLocalFiniteElementMap<Dune::GridView<Dune::DefaultLeafGridViewTraits<const Dune::YaspGrid<2> > >, double, double, 1ul> >, Dune::YaspGrid<2> >’
I fell that trying to specialize my user code will be a hell of a mess.
What is the correct way to implement constructor calls of possibly varying signatures?
any hints would be appreciated!
(ubuntu 16.04, gcc)