Home > OS >  class A with member B that has a constructor argument with a variable type
class A with member B that has a constructor argument with a variable type

Time:01-17

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

  • Related