Home > Mobile >  C vector of custom template class as member
C vector of custom template class as member

Time:04-30

I'm currently coding a program in c using a template class:

template<typename TYPE>
class TemplateClass {
private:
    TYPE t;
};

I have another class which acts as manager of my TemplateClass which should store multiple instances of this class in a vector. Different instances should have different types e.g. int, std::string, etc.. Speaking in Java ways the solution would be to just use something like in the example below but it seems like this is not possible in C .

class ManagerClass {
private:
    // Here seems to be the problem. 
    std::vector<TemplateClass<?>> templates;
}

Is it possible to do something like that?

Thank you for all answers

CodePudding user response:

If you know all the types that will be stored in the std::vector at compile time I'd use an std::variant in such a case.

// This is used for the visitor pattern.
template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
// The below line not needed in C  20...
template<class... Ts> overload(Ts...) -> overload<Ts...>; 

template<typename T>
struct MyClass { T value; };

using types = std::variant<
    MyClass<std::string>, 
    MyClass<int>, 
    MyClass<double>>;

int main() 
{
    std::vector<types> stuff{};
    stuff.push_back(MyClass<std::string>{});
    stuff.push_back(MyClass<int>{});
    stuff.push_back(MyClass<double>{});

    for(const auto& v : stuff) 
    {
        if (std::holds_alternative<MyClass<std::string>>(v)) 
        {
            std::cout << "Im a string\n";
        }
        else if (auto* p{std::get_if<MyClass<int>>(&v)})
        {
            std::cout << "Im an int\n";
        }
        else 
        {
            auto t = std::get<MyClass<double>>(v);
            std::cout << "Im a double\n";
        }

        // Or you can use the visitor pattern.
        std::visit(overload{
            [](const MyClass<std::string>& ) { std::cout << "I'm a string\n"; },
            [](const MyClass<int>& ) { std::cout << "I'm a int\n"; },
            [](const MyClass<double>& ) { std::cout << "I'm a double\n"; },
        }, v);
    }
}

CodePudding user response:

If you can use C 17, you can use std::any or std::variant.

class ManagerClass {
private:
    using variant_type = std::variant<
          TemplateClass<std::string>,
          TemplateClass<int>,
          TemplateClass<double> >;
    std::vector<variant_type> templates;
};

CodePudding user response:

This is one way of doing it via runtime polymorphishm, which is achieved by function overriding. Function overriding occurs when a derived class has a definition for one of the member functions of the base class. That base function is said to be overridden.

#include <iostream>
#include <vector>

using namespace std;

// Base class declaration
class Base {
public:
    virtual void print()
    {
        cout << "Base" << endl;
    }
    virtual ~Base(){}
};

// Derived Class 1 
class Derived1 : public Base {
public:
    void print()
    {
        cout << "Derived1" << endl;
    }
};

// Derived class 2 
class Derived2 : public Base {
public:
    void print()
    {
        cout << "Derived2" << endl;
    }
};


int main()
{
    Base* d1 = new Derived1();
    Base* d2 = new Derived2();

    vector<Base*> myVec;
    myVec.push_back(d1);
    myVec.push_back(d2);

    for (auto i : myVec) {
        i->print();
    }

    delete d1;
    delete d2;

    return 0;
}
  • Related