There's no way to do something like this, in C++ is there?
union {
{
Scalar x, y;
}
Scalar v[2];
};
Where x == v[0] and y == v[1]?
Since you are using C++ and not C, and since they are of the same types, why not just make x a reference to v[0] and y a reference to v[1]
How about
union {
struct {
int x;
int y;
};
int v[2];
};
edit:
union a {
struct b { int first, second; } bee;
int v[2];
};
Ugly, but that's more accurate
Try this:
template<class T>
struct U1
{
U1();
T v[2];
T& x;
T& y;
};
template<class T>
U1<T>::U1()
:x(v[0])
,y(v[1])
{}
int main()
{
U1<int> data;
data.x = 1;
data.y = 2;
}
I've used something like this before. I'm not sure its 100% OK by the standard, but it seems to be OK with any compilers I've needed to use it on.
struct Vec2
{
float x;
float y;
float& operator[](int i) { return *(&x+i); }
};
You can add bounds checking etc to operator[] if you want ( you probably should want) and you can provide a const version of operator[] too.
If you're concerned about padding (and don't want to add the appropriate platform specific bits to force the struct to be unpadded) then you can use:
struct Vec2
{
float x;
float y;
float& operator[](int i) {
assert(i>=0);
assert(i<2);
return (i==0)?x:y;
}
const float& operator[](int i) const {
assert(i>=0);
assert(i<2);
return (i==0)?x:y;
}
};
I was looking for a similair thing and eventually came up with a solution.
I was looking to have a data storage object that I could use as both an array of values and as individual values (for end-user flexibility in writing Arduino libraries).
Here is what I came up with:
class data{
float _array[3];
public:
float& X = _array[0];
float& Y = _array[1];
float& Z = _array[2];
float& operator[](int index){
if (index >= 3) return _array[0]; //Make this action whatever you want...
return _array[index];
}
float* operator&(){return _array;}
};
int main(){
data Test_Vector;
Test_Vector[0] = 1.23; Test_Vector[1] = 2.34; Test_Vector[2] = 3.45;
cout<<"Member X = "<<Test_Vector.X;
cout<<"Member Y = "<<Test_Vector.Y;
cout<<"Member Z = "<<Test_Vector.Z;
float* vector_array = &Test_Vector;
cout<<"Array = {"<<vector_array[0]<<", "<<vector_array[1]<<", "<<vector_array[2]<<"}";
}
Thanks to Operator overloading, we can use the data object as if was an array and we can use it for pass-by-reference in function calls (just like an array)!
If someone with More C++ experience has a better way of applying this end product, I would love to see it!
EDIT: Changed up the code to be more cross-platform friendly
Given your example:
union
{
struct
{
Scalar x, y;
};
Scalar v[2];
};
As others have noted, in general, the standard does not guarantee that there will be no padding between x and y, and actually compilers inserting padding in structures is pretty common behavior.
On the other hand, with solutions like:
struct U
{
int v[2];
int& x;
int& y;
};
U::U()
: x(v[0])
, y(v[1])
{}
what I don't like mainly is the fact that I have to mention x, y twice. For cases where I have more than just a few elements (say 10), this becomes much less readable and harder to maintain - e.g. if you want to change the order of x,y then you have to change the indexes below too (well not mandatory but otherwise order in memory wouldn't match order of fields, which would not be recommended). Also, U can no longer be a POD since it needs a user-defined constructor. And finally, the x & y references consume additional memory.
Hence, the (acceptable for me) compromise I've come up with is:
struct Point
{
enum CoordType
{
X,
Y,
COUNT
};
int coords[CoordType::COUNT];
};
typedef Point::CoordType PtCoord;
With this you can then do:
Point p;
for ( int i = 0; i < PtCoord::COUNT; i++ )
p.coords[i] = 100;
std::cout << p.coords[PtCoord::X] << " " << p.coords[PtCoord::Y] << std::endl;
// 100 100
A bit sophisticated but I prefer this over the references suggestion.
Depending on what "Scalar" is, yes, you can do that in C++. The syntax is almost exactly (maybe even exactly exactly, but I'm rusty on unions) what you wrote in your example. It's the same as C, except there are restrictions on the types that can be in the unions (IIRC they must have a default constructor). Here's the relevant Wikipedia article.
With C++11 you have anonymous unions and structs which just export their definitions to the enclosing scope, so you can do this:
typedef int Scalar;
struct Vector
{
union
{
struct
{
Scalar x, y;
};
Scalar v[2];
};
};
Related
Is there an equivalent to Delphi's absolute in C++? I want to do the following:
// Structure A
struct A
{
double X;
double Y;
double Z;
}
// Structure B
struct B : A
{
double U absolute X;
double V absolute Y;
double W absolute Z;
}
I can use double & U = X in structure B but this will generate an additional pointer and change the size of the structure. Union is - I think - also not a solution, because structure B inherits structure A.
What I really want is to have access to the same memory by accessing for example X or U.
I like the idea of user2079303's answers, but want to inverse it.
Note - the question is named wrong and is violating "what is your real goal" or "show me your Z" rule. We do not need to mimic absolute keyword - it is total nonsense! we want to make pseudonyms for the record properties and use them interchangeably.
What I really want is to have access to the same memory by accessing for example X or U.
The quoted line is the ONLY line in the question that talks about the problem essence - making full pseudonyms.
So, let's start where user2079303 stopped and use the fact that C's unions do not have to be named, like it was used in https://stackoverflow.com/a/13624921/976391
So we just inverse the scopes.
/*union*/ struct coordinates {
/*struct*/ union {
double X;
double U;
};
/*struct*/ union {
double Y;
double V;
};
/*struct*/ union {
double Z;
double W;
};
};
Short version: There is no equivalent of the described language feature.
Long version C++:
There isn't an equivalent in C++. The member reference that you suggest gives you the same syntax, but indeed increases the size of the object.
Another close alternative is a member function, that returns a reference. That has no overhead (assuming inline expansion). A function call has different syntax than referencing a member though. But perhaps having identical syntax with member access is not important so this is what I suggest.
Long version C:
There is no inheritance in C at all, so there is nothing like the described "absolute" in it either.
we have several kinds of coordinates. Some of them are named x, y, z others (in another system) are named u, v, w.
Given this context, I would suggest a union (EDIT: It's better to swap the union and struct relation, see https://stackoverflow.com/a/41148089/2079303):
union coordinates {
struct {
float x, y, z;
} xyz;
struct {
float u, v, w;
} uvw;
};
If you want to interchangeably use XYZ and UVW, you can let each convert to the other.
// forward declare
struct B;
struct A
{
double X;
double Y;
double Z;
operator B() const;
}
struct B
{
double U;
double V;
double W;
operator A() const;
}
A::operator B() const { B b; b.U = X; b.V = Y; b.W = Z; return b; }
B::operator A() const { A a; a.X = U; a.Y = V; a.Z = W; return a; }
I have this code:
class Vector3
{
public:
Vector3() : x(values[0]), y(values[1]), z(values[2])
{ x = y = z = 0; }
float& x;
float& y;
float& z;
private:
float[3] values;
};
class Model
{
public:
Vector3 vertices[64];
};
I'm doing this vector class because I want to deal with the values as X, Y, Z in the code, but for some operations I need a contiguous array of values to be passed to a function.
So the whole array of vertices[64] need to be [x0][y0][z0][x1][y1][z1][x2][y2][z2] etc.
But if I do this:
//Get first address:
void* firstAddress = &vertices[0];
//Or
void* firstAddress = vertices;
I don't have the contiguous array as I need it (the data is all messed up), and I'm guessing it's because of the pointers I have in the Vector3 class.
Is there any way I can do get this functionality that I want? (Having a single array of float but dealing with values as x,y,z)
Firstly, the Standard doesn't define how references should be implemented, but they'll almost certainly occupy actual memory in your class much a pointer members would, ruining the contiguous data packing you're hoping for....
If your focus is more on the vertices container, and you just want x/y/z member access to elements in it, then you could try something like:
template <size_t N>
class Vertices
{
public:
class Proxy
{
public:
Proxy(float* p) : x(p[0]), y(p[1]), z(p[2]) { }
float& x;
float& y;
float& z;
};
Proxy operator[](size_t n) { return Proxy(&d_[n * 3]); }
const Proxy operator[](size_t n) const { return Proxy(&d_[n * 3]); }
private:
float d_[N * 3];
};
You could have member functions instead:
class V3
{
float data[3];
public:
V3() : data{0,0,0} {}
float & x() { return data[0]; }
float & y() { return data[1]; }
float & z() { return data[2]; }
};
You could also omit the constructor and have an aggregate, if that's more suitable.
What you have and array of values pointers (pointing to arrays of 3 floats) with 3 float references (x, y, z). You probably ant something more like:
float & x() { return values[0]; }
float & y() { return values[1]; }
float & z() { return values[2]; }
If I understand your requirement for continuous data in the Model, then your Vector is really an alias to a specific triple of data in the model. No float storage required.
class Model
class Vector
Vector(Model *model_, size_t idx_) : model(model_),idx(idx_) { };
Model *model;
size_t idx;
float & x() { return model->data[3*idx]; }
float & y() { return model->data[3*idx+1]; }
float & z() { return model->data[3*idx+2]; }
float data[64 * 3];
Vector vectors[64];
Model() {
...
for( size_t ii = 0; ii < 64; ii++ ) {
vectors[ii] = new Vector(this,ii);
}
Vector & vector(size_t idx) { return vectors[ii]; }
For a guaranteed contiguous array you need to either copy the data into the array, or use compiler-specific guarantees about memory layout, in particular that
there will be no padding,
and if you want to also access triplets of the array as Vector3 instances, that
accessing a Vector3 at arbitrary address will not cause a trap or inefficiency (we're into alignment here).
It so happens that some common libraries such as OpenCV do make such assumptions for their internal image buffers.
But I'm not entirely sure that the code I've seen has not been platform-adapted. So, in practice you have these choices:
copy the data contiguously to an array (or from it), and/or
use an existing library that provides this kind of functionality, such as OpenCV.
Note that using member functions instead of references buys you nothing wrt. to the contiguous array problem, but it does make the Vector3 potentially assignable.
On further reflection, i was maybe too trigger-happy writing the above. For if you can guarantee total size 3*sizeof(float), and that's almost a given (just get rid of those references), then you are guaranteed that you can access a Vector3 at any address that can hold a float, since C++ guarantees arrays with no padding, and since in such an array a Vector3 can end up at any address that can hold a float. So the in-practice problem reduces to making a decision about supporting compilers or compiler configurations that are unable to make Vector3 of size 3*sizeof(float).
I.e.
struct Vector3
{
float x, y, z;
auto operator[]( int i ) -> float& { return (&x)[i]; }
auto operator[]( int i ) const -> float const& { return (&x)[i]; }
};
static_assert( sizeof( Vector3 ) == 3*sizeof( float ), "Ungood Vector3 size" );
using the fact that members with no intervening access specifier are guaranteed to be in increasing address order.
Disclaimer: off the cuff code, not touched by compiler's hands.
If you keep your Vector3 class a POD you should be able to simply cast your vertices to a float array:
struct Vector3 {
float x;
float y;
float z;
};
class Model
{
public:
Vector3 vertices[64];
float* data() {
return reinterpret_cast<float*>(vertices);
}
};
int main() {
Model m;
for(int i = 0; i < 64; ++i) {
m.vertices[i] = {10+i,100+i,1000+i};
}
float *data = m.data();
for(int i= 0; i < 64*3; ++i) {
std::cout << data[i] << ", ";
}
}
Only problem could be the Allignment of the structure, but should you use c++11, there is a standard way of alligning the structure, using allignasalignas(alignof(float[3])). I don't know if this is really required.
Also, c++11 gives quite a few options on what to do with Vector3, while still considering it as a POD type.
Is it possible in C++ to refer to the same variable using different names without using the preprocessor?
To achieve the same effect as this pseudocode
struct vec3f {
float[3] values;
};
struct color : public vec3f {
#define r values[0]
#define g values[1]
#define b values[2]
};
color c;
c.r = 0.5f;
The following has the right semantics except it allocates space in the struct for the 3 references:
struct color : public vec3f {
float& r;
float& g;
float& b;
color() : r(values[0]), g(values[1]), b(values[2]) { }
};
Is there a way to get this compile-time name substitution without increasing the size of the struct?
How about this?
struct vec3f {
float[3] values;
};
struct color : public vec3f
{
float& r() { return values[0]; }
float& g() { return values[1]; }
float& b() { return values[2]; }
const float& r() const { return values[0]; }
const float& g() const { return values[1]; }
const float& b() const { return values[2]; }
};
I am not sure that you want to use inheritance in this case. You might be better of with a plain old union type:
typedef float vec3f[3];
union color {
vec3f values;
struct {
float r;
float g;
float b;
};
};
color c;
c.values[0] = 10;
assert( c.r == 10 );
As it happens, I first saw a really neat trick for this several years ago.
The idea is that you give the class named variables in order, and then also have a static const member of array-of-pointer-to-member type. The operator[] is overloaded to look up the appropriate pointer-to-member, use it to select the member from this, and return a reference.
This works because pointer-to-members are not ordinary pointers; they're a little more magical than that. (This is what enables you to create un-bound pointers to member functions, and why they can't be used where plain function pointers are expected).
It also means that you don't have to use any casting tricks, rely on any kinds of alignment, non-portable anonymous-union behaviour, or memory layout guarantees, and you still get to refer to the components of the structure as named fields instead of via accessor functions.
ALTERNATIVE 1
You always create a temporary when you want a variable alias. With a good optimizer you will hardly see any performance difference.
struct vec3f
{
float values[3];
};
struct tempvec
{
float &r;
float &g;
float &b;
tempvec( vec3f& bar )
:r(bar.values[0])
, g(bar.values[1])
, b(bar.values[2]){}
};
int main()
{
vec3f temp;
temp.values[0] = 2.40f;
//when you want to alias values[0] as r do this
tempvec(temp).r = 42;
tempvec(temp).g = 42;
return 0;
}
ALTERNATIVE 2
If you can verify that memory layout of vec3f and vec3c is the same on your platform and OS.. taking into account padding/alignment etc... you can do
struct vec3f
{
float values[3];
};
struct vec3c
{
float r,g,b;
};
int main()
{
vec3f temp;
temp.values[0] = 2.40f;
vec3c* alias = reinterpret_cast<vec3c*>(&temp);
alias->r = 4.2f;
alias->g = 4.2f;
alias->b = 4.2f;
return 0;
}
I'm facing a problem in C++ for which I currently don't have an elegant solution. I'm receiving data in the following format:
typedef struct {
int x;
int y;
int z;
}Data3D;
vector<Data3D> v; // the way data is received (can be modified)
But the functions that do the computations receive parameters like this:
Compute(int *x, int *y, int *z, unsigned nPoints)
{...}
Is there a way to modify the way data is received Data3D so that the memory representation would change from:
XYZXYZXYZ
to
XXXYYYZZZ
What I'm looking for is some way of populating a data structure in a similar way we populate an array but that has the representation above (XXXYYYZZZ). Any custom data structures are welcome.
So I want to write something like (in the above example):
v[0].x = 1
v[0].y = 2
v[0].y = 0
v[1].x = 6
v[1].y = 7
v[1].z = 5
and to have the memory representation below
1,6...2,7....0,5
1,6 is the beginning of the x array
2,7 is the beginning of the y array
0,5 is the beginning of the z array
I know that this can be solved by using a temporary array but I'm interested to know if there are other methods for doing this.
Thanks,
Iulian
LATER EDIT:
Since there are some solutions that change only the declaration of Compute function without changing its code - this should be taken into account also. See the answers related to the solution that involves using an iterator.
Iterator-based solution
An elegant solution would be to make Compute() accept iterators instead of pointers. The iterators you provide will have an adequate ++ operator (see boost::iterator for an easy way to build them)
Compute(MyIterator x, MyIterator y, MyIterator z);
There are normally very few changes to make to the function body, since *x, x[i] or ++x will be handled by MyIterator to point to the right memory location.
Quick'n Dirty solution
A less elegant but more straightforward solution is to hold your Data in the following struct
typedef struct {
std::vector<int> x;
std::vector<int> y;
std::vector<int> z;
}DataArray3D;
When receiving the data fill your struct like
void Receive(const Data3D& data, DataArray3D& array)
{
array.x.push_back(data.x);
array.y.push_back(data.y);
array.z.push_back(data.z);
}
and call Compute like this (Compute itself is unchanged)
Compute(&array.x[0], &array.y[0], &array.z[0]);
You could of course change your computer function.
I assume that all operation done on your int* in compute are dereference and increment operation.
I did not test it but you could pass in a structure like this
struct IntIterator
{
int* m_currentPos;
IntIterator(int* startPos):m_currentPos(startPos){};
IntIterator& operator++()
{
m_currentPos += 3;
return *this;
}
IntIterator& operator++(int)
{
m_currentPos += 3;
return *this;
}
int operator*()
{
return *m_currentPos;
}
int& operator[](const int index)
{
return m_currentPos[index*3];
}
};
And initialize it with this
std::vector<Data3D> v;
IntIterator it(&v[0].x);
Now all you need to do is change the type of your compute function arguments and it should do it. If of course some pointer arithmetics are used than it is getting more complex.
Reasonably elegant would be (not compiled/tested):
struct TempReprPoints
{
TempReprPoints(size_t size)
{
x.reserve(size); y.reserve(size); z.reserve(size);
}
TempReprPoints(const vector<Data3D> &v)
{
x.reserve(v.size()); y.reserve(v.size()); z.reserve(v.size());
for (size_t i = 0; i < v.size(); ++i ) push_back(v[i]);
}
void push_back(const Data3D& data)
{
x.push_back(data.x); y.push_back(data.y); z.push_back(data.z);
}
int* getX() { return &x[0]; }
int* getY() { return &y[0]; }
int* getZ() { return &z[0]; }
size_t size() { return x.size(); }
std::vector<int> x;
std::vector<int> y;
std::vector<int> z;
};
So you can fill it with a loop or even try to make the std::back_inserter work with it.
In order to get the syntax you want, you could use something like this.
struct Foo {
vector<int> x;
vector<int> y;
vector<int> z;
struct FooAccessor {
FooAccessor(Foo & f, int i) : x(f.x[i]), y(f.y[i]), z(f.z[i]) {}
int &x, &y, &z;
};
FooAccessor operator[](int i) {
return FooAccessor(*this, i);
}
};
int main() {
Foo f;
f.x.resize(10);
f.y.resize(10);
f.z.resize(10);
f[0].x = 1;
f[1].y = 2;
f[2].z = 3;
for (size_t p = 0; p < 10; ++p) {
cout << f.x[p] << "," << f.y[p] << "," << f.z[p] << endl;
}
}
I'd consider this an ugly solution - changing the way you access your data would likely be "better".
I have a struct that represents a vertex. It has x, y and z fields as well as several others. Recently I came into conclusion that for certain functionality I will need to access the coordinates of the vertex as an array. I didn't want to "pollute" the code with temporary variables or change all places that look like this v.y to this v.coord[1] which is not nice nor elegant. So I thought about using a union. Something like this should work:
struct {
float x,y,z;
} Point;
struct {
union {
float coord[3];
Point p;
};
} Vertex;
This is good, but not perfect. The point class has no point being there. I want to be able to access y coordinate simply by typing v.y (and not v.p.y).
Can you suggest a hack to solve this (or tell me that it is not possible)?
A good C++ approach is to use named accessors that return references to the elements:
class Point {
public:
float& operator[](int x) { assert(x <= 2); return coords_[x]; }
float operator[](int x) const { assert(x <= 2); return coords_[x]; }
float& X() { return coords_[0]; }
float X() const { return coords_[0]; }
float& Y() { return coords_[1]; }
float Y() const { return coords_[1]; }
float& Z() { return coords_[2]; }
float Z() const { return coords_[2]; }
private:
float coords_[3];
};
With this approach, given a Point p;, you can use both p[0] and p.X() to access the initial element of the internal coords_ array.
OK, this should work for you
struct {
union {
float coord[3];
struct
{
float x,y,z;
};
};
} Vertex;
What this code does is that it unions the array with the structure, so they share the same memory. Since the structure doesn't contain a name, it is accessible without a name, just like the union itself.