srinath29 srinath29 - 6 days ago 4
C++ Question

Having difficulty in creating a templatized generic vector which can hold any datatype

As the topic suggests, I am trying to create a vector of which can hold any datatype. I am trying to use templates so that code can be more maintainable for future.

#include<iostream>
#include<memory>
#include<vector>

struct prime{
public:
template<typename T>
T get();
};

template<typename T>
struct foo: prime{
public:
T i;
foo(T k):i(k){
}
template<typename T1>
T1 get(){
return i;
}

};

/*
struct fooString :prime{
public:
std::string i;
fooString(std::string k):i(k){
}
};
*/
int main(){
std::vector<std::shared_ptr<prime>> v;
std::shared_ptr<foo<int>> p1 = std::make_shared<foo<int>>(0);
std::shared_ptr<foo<char>> p3 = std::make_shared<foo<char>>('H');
//std::shared_ptr<fooString> p2 = std::make_shared<fooString>("HK");
v.push_back(p1);
v.push_back(p3);
//v.push_back(p2);
//std::cout<<v[0]->i<<" "<<v[1]->i<<std::endl;
//std::cout<<static_cast<foo<int>>(*v[0]).get();
std::cout<<v[0]->get<int>();
}


The commented code is my different approaches I am trying to solve this issue. But I am not able to crack this. Any suggestions would help me a lot. I tried following this SO but as I said, creating union of different datatypes is difficult to maintain. And also
boost::variant
doesn't help either as I have to give all the types it needs to hold before hand. I don't want that restriction. Can Anyone suggest me whether it is possible or I am just trying to achieve the impossible?
I have another algorithm in my mind which is like cast everything to string and store it. But that approach doesn't look proper.

Thank you :)

Answer

If what you want is to have a container that can store any type, but not actually give you any information about it - it's up to you to just know which type each element is actually storing, then that's precisely what std::any (based on Boost.Any) is for.

The usage in your case would be:

int main(){
    std::vector<std::any> v;
    v.push_back(0);                  // an int
    v.push_back('H');                // a char
    v.push_back(std::string{"HK"});  // a string

    std::cout << std::any_cast<int>(v[0]); // this will throw if v[0] is not an int

    std::string* p = std::any_cast<std::string>(&v[1]); // this will return nullptr
                                                        // if v[1] is not a string, which
                                                        // it is not
}