I've simplified the scenario as much as possible below. Imagine a class that has template specialization using a bool parameter.
template <bool hasExtraParam>
class TestClass {};
template <>
class TestClass<true> {
public:
int param1;
int param2;
};
template <>
class TestClass<false> {
public:
int param1;
};
Now, I would like to have a container class that holds a large amount of these TestClasses as member variables. I want to be able to set the template parameter of each member variable based on the constructor arguments as below:
constexpr bool ep1, ep2, ep3, ep4;
class Container
{
public:
constexpr Container(bool extraParam1, bool extraParam2, bool extraParam3,
bool extraParam4)
{
ep1 = extraParam1;
ep2 = extraParam2;
ep3 = extraParam3;
ep4 = extraParam4;
}
TestClass<ep1> testClass1;
TestClass<ep2> testClass2;
TestClass<ep3> testClass3;
TestClass<ep4> testClass4;
};
How can I achieve this pattern? I want for my actual use-case to pass in a large config struct that has a boolean that will link to each member variable setting its respective template parameter. I cannot wrap my head around how to achieve this and feel like I'm missing some alternate fundamental approach to the problem. Also, I don't this its feasible for Container to have a bunch of templated arguments for scalability purposes since the config struct can be large.
What you are attempting is not possible in C++. Template aarguments can only be specified at compile-time. You will have to instantiate the objects dynamically at runtime instead, eg:
class TestClassBase {
public:
virtual ~TestClassBase() = default;
// common members of both classes...
// virtual methods for both classes to override...
};
template <bool hasExtraParam>
class TestClass {};
template <>
class TestClass<true> : public TestClassBase {
public:
int param1;
int param2;
// override virtual methods as needed...
};
template <>
class TestClass<false> : public TestClassBase {
public:
int param1;
// override virtual methods as needed...
};
class Container
{
public:
Container(bool extraParam1, bool extraParam2, bool extraParam3, bool extraParam4)
{
testClass1 = extraParam1 ? new TestClass<true> : new TestClass<false>;
testClass2 = extraParam2 ? new TestClass<true> : new TestClass<false>;
testClass3 = extraParam3 ? new TestClass<true> : new TestClass<false>;
testClass4 = extraParam4 ? new TestClass<true> : new TestClass<false>;
}
~Container()
{
delete testClass1;
delete testClass2;
delete testClass3;
delete testClass4;
}
TestClassBase* testClass1;
TestClassBase* testClass2;
TestClassBase* testClass3;
TestClassBase* testClass4;
};
Alternatively:
template <bool hasExtraParam>
class TestClass {};
template <>
class TestClass<true> {
public:
int param1;
int param2;
};
template <>
class TestClass<false> {
public:
int param1;
};
class Container
{
public:
Container(bool extraParam1, bool extraParam2, bool extraParam3, bool extraParam4)
{
if (extraParam1)
testClass1.emplace<TestClass<true>>();
else
testClass1.emplace<TestClass<false>>();
if (extraParam2)
testClass2.emplace<TestClass<true>>();
else
testClass2.emplace<TestClass<false>>();
if (extraParam3)
testClass3.emplace<TestClass<true>>();
else
testClass3.emplace<TestClass<false>>();
if (extraParam4)
testClass4.emplace<TestClass<true>>();
else
testClass4.emplace<TestClass<false>>();
}
std::variant<TestClass<true>, TestClass<false>> testClass1;
std::variant<TestClass<true>, TestClass<false>> testClass2;
std::variant<TestClass<true>, TestClass<false>> testClass3;
std::variant<TestClass<true>, TestClass<false>> testClass4;
};