I'm looking to make class A a generic UI Inputbox, that holds a member B that gets a constructor argument with variable type. Class A should then be able to adapt the amount of input boxes depending on the type of the constructor argument of class B.
template<typename coordinatesType>
class B{
B(T coordinates); //constructor defined in cpp
T coordinates; //coordinates of different input type
};
class A{
A(); //in constructor, define the type of UI input boxes, depending on type of B
std::vector<B<T>> vector; //should hold a vector with class B without making class A a template itself
};
Now class A has to be a template class too, because appearently I can't put the member B in the header of class A without giving class A a template argument too (T would be undefined). Since every element of the B vector should have different types, giving class A a template argument and thereby defining the type of each element of the B vector(?) is not an option. There is also the issue that templates objects have to be defined in compile time right?
I'm thinking of building a polymorphic wrapper around class B to avoid this problem, but i don't know wether this is even possible.
CodePudding user response:
Using Polymorphism
As others pointed out in the comments, you can use a non-template base class of B<T>
and store smart pointers in the vector:
#include <vector>
#include <string>
#include <memory>
struct Base {
virtual ~Base(){}
};
template<typename T>
class B : public Base
{
public:
B(T coords) : coordinates{coords} {}; //constructor defined in cpp
T coordinates; //coordinates of different input type
};
class A{
public:
A(){}; //in constructor, define the type of UI input boxes, depending on type of B
std::vector<std::unique_ptr<Base>> vector; //should hold a vector with class B without making class A a template itself
};
int main()
{
A a;
a.vector.emplace_back(new B<int>(5));
a.vector.emplace_back(new B<bool>(false));
a.vector.emplace_back(new B<std::string>("Hello World"));
return 0;
}
Live Code: https://godbolt.org/z/7G89Wf4qG
Using std::variant
If you know all variants that B can be in in advance, you could use std::variant:
#include <vector>
#include <string>
#include <variant>
template<typename T>
class B
{
public:
using value_type=T;
B(T coords) : coordinates{coords} {}; //constructor defined in cpp
T coordinates; //coordinates of different input type
};
using BVariant = std::variant<
B<int>,
B<bool>,
B<std::string>
>;
class A{
public:
A() {} //in constructor, define the type of UI input boxes, depending on type of B
std::vector<BVariant> vector; //should hold a vector with class B without making class A a template itself
};
int main()
{
A a;
a.vector.emplace_back(B<int>(5));
a.vector.emplace_back(B<bool>(false));
a.vector.emplace_back(B<std::string>("Hello World"));
return 0;
}
Live Code: https://godbolt.org/z/dWdbr9z6n