I would like to iterate through a pre-allocated float array with a custom container that does not owns the data, but acts on a segment of it. Example, naming the container class LinhaSobre
:
std::unique_ptr<float[]> data(new float[720]);
...
//creates container to iterate 26 floats starting from from data[12]
LinhaSobre cont(data.get()+12, 26);
//sets those elements to 1.5
for(size_t i = 0; i < cont.size(); i++)
cont[i] = 1.5f;
Here's a possible implementation of the operator[]
:
//...
//LinhaSobre has a member mem0 which is initialized
//as a pointer to where the interval starts
float & LinhaSobre::operator[] (size_t i)
{
return *(mem0+i);
}
Notice that I'm returning a reference from LinhaSobre::operator[]
to data that it does not owns. It should not interfere with the data's lifetime (constructors, destructors).
Now I want to expose the stored data
by another pattern, std::array<float,4>
, and not pure float
. Example, naming the new class LinhaSobre4f
:
std::unique_ptr<float[]> data(new float[720]);
...
//creates container to iterate 4 array<float, 4> starting from from data[12]
LinhaSobre4f l(data.get()+(3*4), 4);
//sets those elements to {1.5f, 2.5f, 3.5f, 4.5f};
for(size_t i = 0; i < l.size(); i++)
l[i] = { {1.5f, 2.5f, 3.5f, 4.5f} };
Notice that I treat the items as an array.
This would lead to some changes in the container class, my main concern is with the operator[]
, here's the full class code:
struct LinhaSobre4f
{
LinhaSobre4f(float * pos_begin, size_t size_):
pos0(pos_begin),
size_(size_){}
std::array<float, 4> & operator[](size_t i)const
{
std::array<float,4> * r =
reinterpret_cast<std::array<float,4>*> (pos0+(4*i));
return *r;
}
size_t size()const
{
return size_;
}
private:
float * pos0;
size_t size_;
};
The operator[]
returns a reference to a block of memory treated as an std::array<float,4>
that never really existed as such, but given the std::array
memory layout guaranties, it works. I'm dubious about this, is it OK? (aside from memory alignment, which I'll guarantee). Am I allowed to expose an object like this, semantically? What is the correct term for this? (I've used fake object in the title).
Here's a live demo of the example. Here's another (the other link sometimes fails)
The C++ standard (I'm reading C++11) defines a std::array
as follows:
The conditions for an aggregate (8.5.1) shall be met.
You are not guaranteed that a std::array
is a POD. The C++ standard guarantees only that it's a class aggregate.
Based on that, I believe that your usage of reinterpret_cast
to convert a POD array of float
s to a std::array
is undefined behavior.
Chances are that it'll work, with your compiler, but you are not guaranteed that this will be portable, or legal.
You might create a plain old reference_type:
struct LinhaSobre4f {
struct Ref {
Ref(float *m): m(m){};
Ref &operator=(std::initializer_list<float> const &l) {
std::copy(l.begin(), l.end(), m);
return *this;
}
private:
float *m;
};
Ref operator[](size_t i) { return m + 4 * i; }
private:
float *m;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With