This is such a simple pattern, there has to be a "nice" way of sorting it out.
I have a function that needs to generate a dynamically sized byte array containing arithmetic data.
// Given that I have a function that kinda looks like this:
void dispatch(std::vector<char> data); //Will take possesion of data.
// The behavior I want, but this breaks strict aliasing
void bad_foo(int c) {
std::vector<char> real_data(c * sizeof(float));
float* raw_data = reinterpret_cast<float*>(real_data.data());
//Fill raw_data with usefull stuff...
dispatch(std::move(real_data));
}
void correct_but_slow_foo(int c) {
std::vector<float> raw_data(c);
//Fill raw_data with usefull stuff...
std::vector<char> real_data(c * sizeof(float));
std::memcpy(real_data.data(), raw_data.data(), c * sizeof(float));
dispatch(std::move(real_data));
}
Unfortunately, it seems even clang's heap elision is not managing to sort out what needs to be done here: see on godbolt
At the very worst, I can make dispatch()
a template, but that would become very messy, and I'm curious to see if there is a way out of this mess I'm overlooking anyways.
Thanks!
Edit: A thought just crossed my mind (immediately after posting the question of course...) : I could treat real_data
as an allocation pool and in-place new the arithmetic data on top of it:
void fixed_foo(int c) {
std::vector<char> real_data(c * sizeof(float));
float* raw_data = new (real_data.data()) float[c];
//Fill raw_data with usefull stuff...
dispatch(std::move(real_data));
}
This looks funky as hell, but I "think" it might be legal. Maybe?
The safest way to get around aliasing rules is to use
memcpy()
but you don't need to do that on a whole second copy of the data. I'd suggest doing all yourfloat
work on a localfloat
variable and thenmemcpy()
ing that to the appropriate location in yourreal_data
buffer an element at a time. Most compilers will optimize that effectively in my experience.