У меня под рукой шаблонный код, в котором классы, которые должны использоваться в качестве параметров шаблона для пользовательского кода, имеют разные сигнатуры конструктора. Моя проблема в том, что я не нашел хорошего способа вызова конструкторов шаблонных классов в моем пользовательском коде. Минимальный рабочий пример может выглядеть так:
#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
}
Здесь у меня есть два класса в библиотеке, один с длинной и несвязанной сигнатурой конструктора, другой с короткой. Я хочу иметь возможность использовать оба из них в качестве параметров шаблона. В моем userClass я как-то должен определить, какие аргументы передавать конструкторам в зависимости от переданного типа.
Я не могу использовать простой if (), потому что компилятор проверит обе подписи и одна из них будет неправильной. Я не могу использовать c ++ 17 для "if constexpr () {}".
Я могу передать шаблонный параметр "ShortConstructorInLibrary" своему классу и без проблем вызвать его конструктор, но когда я использую другой класс, он, конечно, потерпит неудачу из-за неправильной сигнатуры конструктора. До сих пор я использовал уродливый трюк, реализовав два вспомогательных метода, в которых я передаю указатель, а затем позволяю двум методам реализовывать вызовы конструктора, но мне это кажется уродливым. Я также возился с std :: enable_if <>, но не очень далеко. @Mohit предложил использовать частичную специализацию шаблонов, но в реальном коде класс Short ConstructorInLibrary сам по себе шаблонизируется парой ... шаблонных аргументов шаблона. Чтобы дать вам представление:
‘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> >’
Я упал, что попытка специализировать мой код пользователя будет адом беспорядка.
Как правильно реализовать вызовы конструктора с возможной переменной сигнатурой?
любые советы будут оценены!
(Ubuntu 16.04, gcc)