M.K.
M.K.

Reputation: 650

Cast of pointer to vector of different types

I have a function that requires a pointer to vector of type uint16_t. This function fills the vector with the data. I have also object that should hold the data but in form of the vector of type uint8_t. My code looks as following:

void fill1(vector<uint16_t> *data);
void fill2(vector<uint64_t> *data);

class Object
{
    uint32_t data_depth;
    vector<uint8_t> data;
}

Object object1;
object1.data_depth = 16;
fill1((vector<uint16_t>*) &object1.data);

Object object2;
object2.data_depth = 64;
fill2(vector<uint64_t>*) &object2.data);

// somewhere later in the code
if (object1.data_depth == 16)
   vector<uin16_t> * v = (vector<uint16_t>)(&objec1.data);

Is it the save way of pointer conversion of vector of different types?

Upvotes: 1

Views: 3972

Answers (2)

celtschk
celtschk

Reputation: 19721

It is not safe. A vector is, at the fundamental level, not an array of the type, but an object containing some data, including a pointer to an array of the type. That cast you do will cause a misinterpretation of the additional data. Indeed, you are not even guaranteed that the implementation of vector doesn't depend on the type (I doubt that this is done anywhere — with the exception of vector<bool> which has to be implemented differently — but it is definitely allowed, as long as all individual implementations conform to the standard).

You could use boost::variant to allow vectors of different base types to be stored in Object::data.

Here's how your code might look like:

#include <boost/variant.hpp>

class Object
{
  boost::variant<std::vector<uint16_t>, std::vector<uint64_t> > data;
};

struct fill_visitor: boost::static_visitor<>
{
  template<typename T>
   void operator()(std::vector<T>& v)
  {
    fill(&v);
  }
};

// ...

boost::apply_visitor(fill_visitor(), object1.data);

Upvotes: 1

Joel
Joel

Reputation: 1145

You could probably do something like this:

template <typename T>
void fill(vector<unsigned char>& data)
{
    assert(data.size() % sizeof(T) == 0);

    T* pReinterpreted = reinterpret_cast<T*>(&data[0]);
    size_t count = data.size() / sizeof(T);

    // do some stuff with your array of reinterpreted values
}

class Object
{
    uint32_t data_depth;
    vector<unsigned char> data;
}

Object object;
fill<uint16_t>(object.data);

Naturally, this is unsafe code so I wouldn't do it unless you know exactly what the trade-offs are here.

Upvotes: 3

Related Questions