Iterate through variables in a struct c++ [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I need a struct that can hold 3 coordinates as separate variables, but I also need a way to iterate through them. For now, I am doing it like this:
struct Vector3
{
float coords[3];
float& x = coords[0];
float& y = coords[1];
float& z = coords[2];
};
This way I can access each individual variable as well as iterate through all of them using the coords array. Problem is: this is very unefficient, both in memory usage and in performance cost. Is there a better solution?

As suggest (by underscore_d) in a comment the preferred way is to provide accessor functions.
On any realistic compiler they'll be optimised away so no space or performance issue.
struct Vector3 {
float coords[3];
float& x() { return coords[0]; }
float& y() { return coords[1]; }
float& z() { return coords[2]; }
float x() const { return coords[0]; }
float y() const { return coords[1]; }
float z() const { return coords[2]; }
};
Here's a little program that gives it a run out.
#include <iostream>
struct Vector3 {
float coords[3];
float& x() { return coords[0]; }
float& y() { return coords[1]; }
float& z() { return coords[2]; }
float x() const { return coords[0]; }
float y() const { return coords[1]; }
float z() const { return coords[2]; }
};
void dump(const std::string& title,const Vector3& v3){
std::cout << title << '\n';
std::cout << "{ " << v3.coords[0] << " , " << v3.coords[1] << " , " << v3.coords[2] << " }\n";
std::cout << "x=" << v3.x() << " y=" << v3.y() << " z=" << v3.z() << '\n' << std::endl;
}
int main() {
Vector3 v3{};
dump("v3 0:",v3);
v3.x()=7.0f;
v3.y()=3.141f;
v3.z()=276.0f;
dump("v3 1:", v3);
Vector3 v3c{};
dump("v3 c 0:", v3c);
v3c=v3;
dump("v3 c 1:",v3c);
return 0;
}
Don't overlook that the assignment v3c=v3 now works 'out of the box'. Bonus!
The references broke the default assignment operator. References can't be assigned to be references to other things (in this case the coordinate in the other object - as C++ sees it).
I've provided two sets of getters - const and non-const - you may not be managing const-ness.
You mention iteration. If you this to the structure definition:
const float * begin() const { return coords;}
const float * end() const { return coords + 3; /* Yes 3 */}
float * begin() { return coords;}
float * end() { return coords + 3; /* Yes 3 */}
You can use C++ ranged-for loops : for(auto curr : vec ) as well.
This snippet sets all the coords of v3 to 7.0.
for(auto& curr : v3){
curr=7.0f;
}
I also recommend adding a constructor: Vector3():coords{} {} to the struct to initialise all the coordinates to zero. It has a tiny overhead but experience shows its usually the best to avoid 'weird' bugs down the line.
The modern recommendation is to prefer double over float unless you have good reason. I at least recommend creating a master typedef float float_type; and using that consistently in your code. It won't save you any re-engineering but it will reduce the rework if you change take. Also observe "almost always auto".
constexpr float_type zero{0}; may also help.
Expected program output:
v3 0:
{ 0 , 0 , 0 }
x=0 y=0 z=0
v3 1:
{ 7 , 3.141 , 276 }
x=7 y=3.141 z=276
v3 c 0:
{ 0 , 0 , 0 }
x=0 y=0 z=0
v3 c 1:
{ 7 , 3.141 , 276 }

Iterate through variables in a struct c++
There is no standard way to do this.
You could for example implement a custom iterator to do this. However, for random access, an array is likely to produce efficient code.
This way I can access each individual variable as well as iterate through all of them using the coords array. Problem is: this is very unefficient
You don't need the references to access individual elements. This works just fine:
struct Vector3
{
float coords[3];
} v;
v.coords[0] = 42; // access first element

Related

Unions in C++ (Please explain it)

#include <iostream>
#define print(x) std::cout << x
#define println(x) std::cout << x << std::endl
struct Vector2 {
float x, y;
};
struct Vector4 {
union {
struct {
float x, y, z, w;
};
struct {
Vector2 a, b;
};
};
};
void PrintVector2(const Vector2& vector) {
println(vector.x << ", " << vector.y);
}
int main() {
Vector4 vector = { 1, 2, 3, 4 };
vector.x = 2;
vector.z = 500.0f;
PrintVector2(vector.a);
PrintVector2(vector.b);
}
Could anyone explain what's going on in this piece of code please ?, I didn't understand what unions are
and how they work :/ !
This is the output
2, 2
500, 4
The behaviour of the code is undefined.
This is little more than an elaborated union type-pun. This is not allowed by the C++ standard, as the C++ union has the concept of an active member. Once the active member is set, you cannot read another member in a defined manner. (You can of course change the active member by reassignment.)
Do Google the terms I've italicised: there's little point in going into more depth here.

Create a sum of two Array instances

The essence of what I want to do is to take two instances of Vector2D and create a third vector that is to be returned and made into the third instance. The problem I am facing is that I am not entirely sure on how to go ahead in doing so. I have tried to find the syntax for sending in instances, if there is such a one, but I have not managed to find anything useful in any of my books.
#include<iostream>
#include<string>
#include<array>
using namespace std;
class vector2D
{
public:
array<float, 2> get()
{
return xy_coord;
}
void set(float x, float y)
{
xy_coord[0] = x;
xy_coord[1] = y;
}
array<float, 2> vectorAdd(a, b)
{
array<float, 2> c;
for (int i = 0; i < 2; i++)
{
c[i] = a[i] + b[i];
}
return c;
}
private:
array<float, 2> xy_coord;
};
int main()
{
string y;
vector2D a, b, c;
array<float, 2> temp;
a.set(2.0, 3.0);
b.set(4.0, 5.0);
temp = c.vectorAdd(a, b);
c.set(temp[0], temp[1]);
getline(cin, y);
}
The idea is to send in the instances a and b to vectorAdd and sum them up and then set c equal to the returned value (I am sure there is a better way to write the code in the main(), but I am not sure how). In short, what would a and b need to be defined as to make this work, assuming it can work at all.
Maybe you could do something like this instead, so you don't have to pass array around:
#include <iostream>
class Vector2D
{
private:
double _x;
double _y;
public:
Vector2D() = delete;
Vector2D(double x, double y) : _x(x), _y(y) {}
double X() const { return _x; }
double Y() const { return _y; }
Vector2D operator+(Vector2D const &v) const
{
return Vector2D(X() + v.X(), Y() + v.Y());
}
};
int main()
{
Vector2D v1(10.0, 20.0);
Vector2D v2(100.0, 200.0);
Vector2D v3 = v1 + v2;
std::cout << v3.X() << " " << v3.Y();
return 0;
}
Prints:
110 220
Do you need to use array<float, 2>? Have you thought of using pair<float, float>?
A lot (all?) of the operations that you have in your Vector2D class come for free with Pair<>.
Then you just create operator+ as others have suggested.
#include <iostream>
#include <utility>
using namespace std;
using Coord = pair<float, float>;
template <typename L, typename R>
Coord operator+(const L& x, const R& y) { return std::make_pair(x.first + y.first, x.second + y.second); }
int main()
{
Coord a { 5.0f, 6.0f };
Coord b { 7.0f, 9.0f };
Coord c = a + b;
std::cout.precision(5);
std::cout << "c= (" << std::fixed << c.first << ", " << c.second << ")" << std::endl;
return 0;
}

Getters And Setters C++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Ok Guys My Question here is simple.. I want to construct a getter and setter for diffrent value type.. Basically function overloading but with getters and setters.. i tried it like this
#include <iostream>;
class Vectors {
public:
Vectors() {};
Vectors(int a, int b) {
x = a, y = b;
}
int getX() {
return x;
}
int getY() {
return y;
}
float getX() {
return (float)x;
}
float getY() {
return (float) y;
}
friend Vectors operator+(const Vectors& v1, const Vectors& v2);
friend Vectors operator/(const Vectors& v1, const Vectors& v2);
protected:
int x, y;
private:
};
Vectors operator+(const Vectors& v1, const Vectors& v2) {
Vectors brandNew;
brandNew.x = v1.x + v2.x;
brandNew.y = v1.y + v2.y;
return (brandNew);
};
Vectors operator/(const Vectors& v1, const Vectors& v2) {
Vectors brandNew(v1.x / v2.x, v1.y/v2.y);
return brandNew;
}
int main() {
Vectors v1(2, 3);
Vectors v2(4, 5);
Vectors v3;
v3 = v1 + v2;
Vectors v4 = v1 / v2;
std::cout << "VECTOR 4 X : " << v4.getX() << std::endl;
std::cout << "VECTOR 4 Y : " << v4.getY() << std::endl;
std::cout << "Vector V3 X : " << v3.getX() << std::endl;
std::cout << "VECTOR V3 Y : " << v3.getX() << std::endl;
}
But Obviously it said cant do function overloading and the only type diffrent is return type..
Of course you're not using enough templates. Templates solve problems in C++. Use them. Love templates.
struct YeeTemplates {
float F;
template <typename T>
T getF() { return F; }
} y;
float f = y.getF<float>();
int i = y.getF<int>();
There's no way to overload a function without changing the arguments that I'm aware of. You need to either change the function name (call it getXFloat() or something) or just to the cast after calling the function like:
float the_x_value = static_cast<float>(vec.getX());
I would go for the second option.
You can't overload methods based on return type.
You can overload functions on it's input paramaters.
For example:
void fun1(int a,char b);
void fun1(float a,char b);
void fun1(float a,int a,char b);
http://www.tutorialspoint.com/cplusplus/cpp_overloading.htm
Another option you have is to not return the result as the return value. Instead:
...
void getX( float& result) const {
result = static_cast<float>(x);
}
void getX( int& result) const {
result = x;
}
...
Just adding to the list of options, not saying this is the best solution.

Getting vector from matrix by overloading subscript operator()

I want to do something like this:
Matrix m; // (4x4 matrix)
Vector4 v; // (4-elements vector)
m(0) = v; // replace first 4-elements matrix row by vector v
v = m(0); // replace vector v by first 4-elements matrix row
heres my code:
Vector4& Matrix::operator() (unsigned row)
{
return Vector4(mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}
Vector4 Matrix::operator() (unsigned row) const
{
return Vector4(mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}
the second operator works fine, but when I try to compile first one, I get this error:
error: invalid initialization of non-const reference of type ‘Vector4&’ from an rvalue of type ‘Vector4’
So where is the problem? It's good idea to overload operator() instead of operator[] in this case?
By getting only one element from matrix I use the other two operators:
float& Matrix::operator() (unsigned row, unsigned col)
{
return mat[row][col];
}
float Matrix::operator() (unsigned row, unsigned col) const
{
return mat[row][col];
}
Edit 1 (almost solution)
I think I found some solution. The first operator has been replaced to:
Matrix::MatrixHelper operator() (unsigned row)
{
MatrixHelper m;
m.f1 = &mat[row][0];
m.f2 = &mat[row][1];
m.f3 = &mat[row][2];
m.f4 = &mat[row][3];
return m;
}
heres the definition of MatrixHelper class:
class MatrixHelper
{
public:
friend class Matrix;
void operator= (const Vector4& v)
{
*f1 = v.x;
*f2 = v.y;
*f3 = v.z;
*f4 = v.w;
}
private:
float* f1;
float* f2;
float* f3;
float* f4;
};
now is possible to do something like that:
m(0) = Vector4(3,3,3,3);
but then occurs new problem, when calling this:
(m)(0) * someScalar;
the second operator is never called, so I have to implement them in my MatrixHelper class right? I'm on the right track?
Edit 2
OK this problem would be solved if the two operators would be working at the same time. But now only one of them can be enabled. I can not understand why always is working the first operator, for example having this code (just example):
Vector4& Matrix::operator() (unsigned row)
{
std::cout << "Operator one is working now\n";
}
Vector4 Matrix::operator() (unsigned row) const
{
std::cout << "Operator two is working now\n";
}
No matter if I am doing
m(0) = Vector(4,4,4,4)
or
Vector4 v = m(0)
always is working the first operator. Why?
Edit 3 (Solution)
I have found some other solution. Now all it's working, but performance may be a little problem. Solution not resolved in the way I wanted and it is a little far-fetched. Here's the code:
Operators:
Vector4 Matrix::operator() (unsigned row)
{
return Vector4 (&mat[row][0], &mat[row][1], &mat[row][2], &mat[row][3]);
}
Vector4 Matrix::operator() (unsigned row) const
{
return Vector4 (mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}
as you can see the first operator returns a vector that takes pointers. The hard work happens now in Vector4 class instead of Matrix. Vector4 has now an extra constructor:
Vector4(float* x, float* y, float* z, float* w)
{
this->px = x; this->py = y; this->pz = z; this->pw = w;
this->x = *x; this->y = *y; this->z = *z; this->w = *w;
pointer = true;
}
first line are pointers, second - variables, and third line is a boolean type variable witch means what constructor has been called (normal or pointers).
Now comes the last operator (operator=):
Vector4 operator= ( const Vector4& v)
{
if ( pointer )
{
*px = x = v.x;
*py = y = v.y;
*pz = z = v.z;
*pw = w = v.w;
}
else
{
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
}
If pointer is true that means - px, py, pz and pw are pointers to some row elements in matrix, and we have to change them. Else - just normal vector.
So now question... it is bad bad solution, or just bad? :D
The Vector4 you are instantiating in the errored code is an r-value which is temporary. Aside from the fact that you can't assign it to a non-const reference, it will be destroyed when your function exits and the return value would be an invalid stack location.
One solution would be to return a different object by value that stores references to the individual elements you need and allows you to act upon them in a transparent way.

sorting a column with rows

I have a set of points (x,y,z). I want to sort these data using first column and 2nd and 3rd columns should be rearranged according to the sorting 1st column. is it possible to do this in c++, if so could you pls help me.
Herewith I am attaching codes of my implementation but I got a error message “invalid conversion from ‘const’ vod*’ to ‘const int [*][3]’ “ in line 31 and 32. I tried this using several methods but my effort was not success yet. I used here ‘qsort’ for this, are there any other methods or can I use ‘sort’ in to do this. Since I have a very big data set I wish to use a fast method.
So what I need at the end the data set which is sorted using only 1st column like following example:
before sort
34 12 12
12 34 15
24 20 34
13 11 10
40 23 32
after sort
12 34 15
13 11 10
24 20 34
34 12 12
40 23 32
if any good methods help me to write codes …thanks
#include <iostream>
#include <cstdlib>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
class Point
{
private:
double x;
double y;
double z;
public:
Point(){};
~Point(){};
Point(double X, double Y, double Z){
x=X;y=Y;z=Z; }
double X(){return x;}
double Y(){return y;}
double Z(){return z;}
};
int cmp ( const void *pa, const void *pb ) {
const int (*a)[3] = pa;
const int (*b)[3] = pb;
if ( (*a)[1] < (*b)[1] ) return -1;
if ( (*a)[1] > (*b)[1] ) return +1;
return 0;
}
int main ( ) {
vector<Point> points;
int input_x,input_y,input_z;
int i=0;
while(i<6){//data set,it is a example, actual data come from a file
cout<<"x: ";cin>>input_x;
cout<<"y: ";cin>>input_y;
cout<<"z: ";cin>>input_z;
Point point(input_x,input_y,input_z);
points.push_back(point);
i++;
}
for (int i=0;i<points.size();i++){//before sort
cout<<points[i].X()<<" "<<points[i].Y()<<" "<<points[i].Z()<<endl;
}
qsort( points, 6, sizeof points[0], cmp );
for (int i=0;i<points.size();i++){//after sort
cout<<points[i].X()<<" "<<points[i].Y()<<" "<<points[i].Z()<<endl;
}
system("PAUSE");
return 0;
}
It's almost certainly easiest to use std::sort instead of qsort:
class Point {
int x, y, z;
public:
Point(int x, int y, int z) : x(x), y(y), z(z) {}
bool operator<(Point const &other) {
return x < other.x;
}
// skipping the reading and other stuff for now...
};
int main() {
std::vector<Point> points;
// add some Points to `points` here.
// sort using order defined in Point::operator<:
std::sort(points.begin(), points.end());
return 0;
}
Edit: to keep the comparison separate from the items being compared, you use a separate function or functor to do the comparison, and pass that to std::sort. There are a few things about your class that you really want to change in any case though -- at the very least, since your Point::X(), Point::Y() and Point::Z() don't modify the Point object, you want to make them const member functions. Once you've done that, the sorting is fairly trivial:
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
class Point {
double x, y, z;
public:
double X() const { return x; }
double Y() const { return y; }
double Z() const { return z; }
Point(double x=0.0, double y=0.0, double z=0.0) : x(x), y(y), z(z) {}
};
namespace std {
ostream &operator<<(ostream &os, Point const &p) {
return os << "(" << p.X() << ", " << p.Y() << ", " << p.Z() << ")";
}
}
struct byX {
bool operator()(Point const &a, Point const &b) {
return a.X() < b.X();
}
};
int main(){
std::vector<Point> points;
for (int i=0; i<10; i++)
points.push_back(Point(rand(), i, i));
std::cout << "Unsorted:\n";
std::copy(points.begin(), points.end(),
std::ostream_iterator<Point>(std::cout, "\n"));
std::sort(points.begin(), points.end(), byX());
std::cout << "\nSorted:\n";
std::copy(points.begin(), points.end(),
std::ostream_iterator<Point>(std::cout, "\n"));
return 0;
}
Technically, I suppose I should add one more minor detail: if the x value in any of your points is a NaN, this won't work correctly. A NaN isn't equal to anything (not even itself) which violates the strict weak ordering required for std::sort.
The arguments of the cmp function are actually const Point *px in your case. You may not be able to declare them as arguments this way, but you can surely cast the void pointers later.
Further reference here.