Have a Union typedef and want to create a vector of that Union Type, but want to load a vector of other type to it, error says I need a constructor.
union:
typedef union
{
uin32_t uin;
int32_t sin;
float flt;
uitn8_t u8n[4];
}rDATA
Underlying architecture is 32 bits, so the last element does cover all above types, I am receiving data in a float array, I can convert that float array to a vector, but can't seem to load the data into a rDATA vector, so:
vector<float> vector_array(&array[0], &array[0] + array_size)
std::vector<LEAP_DATA_UNIT> DATA_vector(vector_array)
An option that produces very readable code, is to create an iterator that adapts the source type (e.g. float
) to the union
type. This allows the direct use of the regular std::vector
constructor.
The following code gives an idea of how it might work. You could generalize it to take a lambda
that could do an arbitrary transformation on an element. You would also probably want to make a make_iterator_adaptor
method for easy creation.
#include <cassert>
#include <type_traits>
#include <iterator>
#include <vector>
union Data {
uint32_t uin;
int32_t sin;
float fin;
uint8_t u8n[4];
};
template<class base_iterator>
struct iterator_adaptor {
using iterator_category = std::input_iterator_tag;
using different_type = typename base_iterator::difference_type;
using value_type = Data;
using pointer = Data*;
using reference = Data&;
iterator_adaptor(base_iterator iter)
: iter_(iter) {
}
value_type operator*() const {
Data d;
d.fin = *iter_;
return d;
}
iterator_adaptor& operator++() {
++iter_;
return *this;
}
iterator_adaptor operator++(int) {
iterator_adaptor tmp = *this;
++(*this);
return tmp;
}
friend bool operator==(const iterator_adaptor& a, const iterator_adaptor& b) {
return a.iter_ == b.iter_;
}
friend bool operator!=(const iterator_adaptor& a, const iterator_adaptor& b) {
return not (a == b);
}
private:
base_iterator iter_;
};
namespace std {
template<class T>
struct iterator_traits<iterator_adaptor<T>> {
using value_type = typename iterator_adaptor<T>::value_type;
using difference_type = typename iterator_adaptor<T>::different_type;
using iterator_category = typename iterator_adaptor<T>::iterator_category;
using pointer = typename iterator_adaptor<T>::pointer;
using reference = typename iterator_adaptor<T>::reference;
};
};
int main(int argc, const char *argv[]) {
std::vector<float> floats = { 1.0, 2.0, 3.0, 4.0, 5.0 };
std::vector<Data> data(iterator_adaptor(floats.begin()), iterator_adaptor(floats.end()));
for (auto i = 0; i < floats.size(); ++i)
assert(floats[i] == data[i].fin);
return 0;
}