For weeks I've been searching the internet about heterogeneous lists (vector
, array
, list
) in c++, however, in all sites and forums, the answer is the same: boost::any
, but I wanted a way to do it in pure C ++. I developed this:
#include <iostream>
#include <typeinfo>
#include <vector>
using namespace std;
//Compiler version g++ 6.3.0
class any
{
public:
auto get() {}
};
template<typename T>
class anyTyped : public any
{
public:
T val;
anyTyped(T x)
{
val = x;
}
T get()
{
return val;
}
};
class queue
{
vector<any*> x;
int len = 0;
public:
queue()
{
x.resize(0);
}
template<typename T>
void insert(T val)
{
any* ins = new anyTyped<T>(val);
x.push_back(ins);
len++;
}
int size()
{
return len;
}
auto& at(int idx)
{
return x[idx]->get();
}
};
int main()
{
queue vec;
vec.insert(5); //int
vec.insert(4.3); //float
vec.insert("txt"); //string
for (int i = 0; i < vec.size(); i++)
{
cout << vec.at(i);
}
return 0;
}
But i get the this error:
source_file.cpp: In member function 'auto& queue::at(int)':
source_file.cpp:55:23: error: forming reference to void
return x[idx]->get();
^
source_file.cpp: In function 'int main()':
source_file.cpp:70:9: error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'void')
cout << vec.at(i);
~~~~~^~~~~~~~~~~~
I know the problem is in using auto
as the return type, either in auto get()
in the any
class, or in auto& at(int idx)
in the queue
class, but I don't know how to fix.
In order to be stored, all heterogenous data must be brought down to something homogeneous in C++. std::any
is no exception. To make things homogeneous there are, most importantly, inheritance and type erasure (any
is an instance of the latter).
Applied to your example, this could mean, for example, that you have to specify the return type of get
to a fixed type. In the best case, this would be the std::common_type
of all your used types T
.
To get the idea:
anyTyped<double> anyDouble{1.0};
anyTyped<int> anyInt{2};
std::vector<std::function<double()> > anyStore; //the chosen homogenous type is 'double'
//get() should be const, otherwise add a 'mutable'
anyStore.push_back([anyDouble]() { return anyDouble.get(); });
anyStore.push_back([anyInt]() { return anyInt.get(); });
You can now call
auto x = anyStore[0](); //x is a double
x = anyStore[1]();
You get a double
in both cases, but you wont get back your int
.
All runtime dealing with heterogenous builds on a similar principle, but might be more sophisticated -- which basically means that more layers are involved until the chain ends in an homogenous type.