How might I initialise a std::vector from an array of structs, where the struct contains a union of different types. In other words, the array is used to store a number of values of a specific type, which can be int, char* etc.
This is my solution so far but I’m looking for a better approach:
The convert function returns a vector<int> if it stores ints or a vector<std::string> if it stores char*.
The Value type below is a struct containing a union called value. The Container class below points to a buffer of such Values.
// union member getter
class Getter
{
public:
void operator()(int8_t& i, const Value& value)
{
i = value.value.i;
}
void operator()(std::string& s, const Value& value)
{
s = std::string(value.value.s);
}
...
};
template<class T>
std::vector<T> convert(Container* container)
{
std::vector<T> c;
c.reserve(container->nrOfValues);
Getter g;
for(int i=0;i<container->nrOfValues;i++)
{
T value;
g(value, container->values[i]);
c.push_back(value);
}
return c;
}
Your problem is the union gives a different name to each value, which causes the need for a function that converts a name to a type, such as Getter::operator() returning a type and getting a named member of the union.
There isn’t much you can do with this. You can save a variable declaration and a copy/string constructor on each item, but that’s about it.
If you can’t modify the original struct, you could initialize the vector with a length set of default value (which must be passed in), then iterate through using the getter as:
Notice that this starts getting cumbersome in iterating the index and the iterator and verifying both are still valid in case of an accident…
If you can modify the original struct:
Then your for loop becomes:
Note: You might create the vector and pass it as an argument to the copy function since it involves copying the data over during the return.