Changing values in polymorphic boost::shared_ptr (inside std::vector) - c++

I have the following base calibration struct:
struct Standard
{
public:
unsigned long ulCamID;
std::string sCalibrationModel;
float fC;
float fXh;
float fYh;
Standard()
{
ulCamID = 0;
fC = fXh = fYh = 0.0;
}
virtual ~Standard()
{
}
};
And derived structs such as:
struct Aus: public Standard
{
public:
float fK1;
float fK2;
float fK3;
float fP1;
float fP2;
float fB1;
float fB2;
Aus()
{
fC = fXh = fYh = fK1 = fK2 = fK3 = fP1 = fP2 = fB1 = fB2 = 0.0;
}
};
Because I do not know at compile how many Calibrations I will need, nor which calibration models, I thought it convenient to put it into a std::vector and use boost::shared_ptr to point to them. I do this like so:
typedef boost::shared_ptr<CalibrationModels::Standard> shr_ptr;
std::vector<shr_ptr> vec;
shr_ptr p(new CalibrationModels::Aus);
vec.push_back(p);
p.reset(new CalibrationModels::Brown);
vec.push_back(p);
This seems to work fine (the debugger reports that the pointers inside the vector point to the derived struct). However, I have difficulties now to access/change the values inside the vector. If I try something like this:
boost::dynamic_pointer_cast<CalibrationModels::Aus>(vec.at(0)).px->fK3 = 1.3221e-9
It tells me that px is private ( ‘boost::shared_ptr::element_type* boost::shared_ptr::px’ is private element_type * px; ).
What is the proper way to access and manipulate the values inside those pointers to derived structs?

The problem you have is that px is a private member of the smart pointer. To access your class boost provides the -> operator. You can use that to access the pointer as you would use it for a regular pointer. This would change your line to this:
boost::dynamic_pointer_cast<CalibrationModels::Aus>(vec.at(0))->fK3 = 1.3221e-9;
^^ Difference here
Note that, if you actually need the value, you can use the get() method to get the pointer that is stored in the shared_ptr.

Related

shared_ptr in c++, getting points to faces

I have the following class for points:
class MyPoint
{
public:
// Constructor
MyPoint(double, double, double);
// Destructor
virtual ~MyPoint(){};
protected:
private:
double x;
double y;
double z;
};
I would like to create a vector of myPoints to store some data:
vector <MyPoint> vectorOfPoints
for (int i = 0; i < 10 ; i++)
{
vectorOfPoints.push_back(MyPoint(1,2,3));
}
And I would like to create a class called myFaces to store the address of the points that make up a face.
e.g.,
Face A is built with vectorOfPoints[0], vectorOfPoints[2], vectorOfPoints[5] and vectorOfPoints[6].
How can I pass a vector with the addresses of the above entries to the class myFace?
class myFace
{
public:
// Constructor
myFace(int, vector<std::shared_ptr<Point> > );
// Destructor
virtual ~myFace(){};
protected:
private:
int nPointsInFace_;
vector<std::shared_ptr<Point> > refToPointsThatMakeUpThisFace_;
};
Would really appreciate the help!
Face A is built with vectorOfPoints[0], vectorOfPoints[2], vectorOfPoints[5] and vectorOfPoints[6].
You want indexes. So store that!
class myFace
{
vector<size_t> indexes_;
public:
myFace(vector<size_t>) ...
};
You don't need nPointsInFace_ because its the size of indexes_.
You can use a smaller type if you know you dont need so many, like uint16_t.
You avoid messing with pointers (and shared_ptr which is overkill for single 3D points).
You can do checked accesses.
Probably the easiest answer is to change your vector of points to a vector of pointers to points. Something like this:
vector <std::shared_ptr<MyPoint>> vectorOfPoints;
for (int i = 0; i < 10 ; i++)
{
vectorOfPoints.push_back(std::make_shared<MyPoint>(1,2,3));
}
Now you can very easily just cherry pick whichever points you want to pass to your myFace constructor. Using managed pointers like std::shared_ptr is an all-or-nothing proposition.
What if I put something like
class myFace
{
public:
// Constructor
myFace(int, vector<myPoint*>);
// Destructor
virtual ~myFace(){};
protected:
private:
int nPointsInFace_;
vector<myPoint*> refToPointsThatMakeUpThisFace_;
};
After initializing the vectorOfPoints. If I can
std::vector<Point*> listOfPoints (4);
listOfPoints[0] = vectorOfPoints[0]
listOfPoints[1] = vectorOfPoints[2]
listOfPoints[2] = vectorOfPoints[5]
listOfPoints[3] = vectorOfPoints[6]
Face myFace (4, listOfPoints);
This should create a face with the address of the vectorOfPoints, no?
More classes will have pointers the vectorOfPoints, is makes sense to use a shared_ptr, right?

Save and load function pointers to file

Consider the following code:
typedef float (*MathsOperation)(float _1, float _2);
struct Data
{
float x, y;
MathsOperation op;
};
Data data[100];
float Add(float _1, float _2){//add}
float Sub(float _1, float _2){//subtract}
float Mul(float _1, float _2){//multiply}
// other maths operations
for (int i = 0; i < 100; ++i)
{
// assign one of the maths operators above to data struct member op
// according to some condition (maybe some user input):
if(condition1) data[i].op = &Add;
if(condition2) data[i].op = &Sub;
if(condition3) data[i].op = &Mul;
// etc.
}
Now I'd like to somehow save the dataarray to a file and load it later (maybe in another program which doesn't know about the conditions that were used to assign the operators to each array element). Obviously, the pointers would be different every time I ran the application. So, my question is what is the best way to do this?
You can't store "functions" as data anyway, and as you say, storing pointers in external media doesn't work. So, what you have to do in this case is store an operator value, e.g.
enum Operator
{
Op_Add,
Op_Sub,
Op_Mul,
Op_Largest // For array size below.
};
And instead of:
if(condition1) data[i].op = &Add;
if(condition2) data[i].op = &Sub;
if(condition3) data[i].op = &Mul;
have:
if(condition1) data[i].op = Op_Add;
if(condition2) data[i].op = Op_Sub;
if(condition3) data[i].op = Op_Mul;
Since that is an integer type value, it can be stored in a file, and you can then do:
// Or `fin.read(reinterpret_cast<char*>(data), sizeof(data))
fin >> op >> x >> y;
if (op == Op_Add) ...
else if (op == Op_Sub) ...
Or have a function pointer array that you index with op... In other words:
typedef float (*MathsOperation)(float _1, float _2);
...
MathsOperation mathsOps[Op_Largest] = { &Add, &Sub, &Mul };
...
mathsOps[op](x, y);
...
If I where you I would build an index, where you could register your operators
static std::array<MathsOperation> MathsOperations;
MathsOperations.push_back(Add);
MathsOperations.push_back(Sub);
MathsOperations.push_back(Mul);
int getIdx(MathsOperation op) {
return std::find(MathsOperations.begin(), MathsOperations.end(), op) - MathsOperations.begin();
}
and put it in a .h file just after the MathsOperation definitions
Then rather then saving the function pointer, you could just save the relevant index and access the operator afterwards
int opidx = getIdx(Add);
MathsOperator op = MathsOperator[idx];
Non-portable, but almost certain to work if all your functions are in the same module:
template<typename FuncT>
intptr_t FunctionPointerToId( FuncT* fptr )
{
return reinterpret_cast<intptr_t>(fptr) - reinterpret_cast<intptr_t>(&Add);
}
template<typename FuncT>
FuncT* FunctionPointerFromId( intptr_t id )
{
return reinterpret_cast<FuncT*>(i + reinterpret_cast<intptr_t>(&Add));
}
This assumes that your implementation preserves relative addresses of functions within the same module (most platforms do guarantee this as implementation-specific behavior, since dynamic loaders rely on this). Using relative addresses (aka "based pointers") allows it to still work even if the module is a shared library that gets loaded at a different base address each time (e.g. ASLR).
Don't try this if your functions come from multiple modules, though.
If you have the ability to build and maintain a list of the functions, storing an index into that list is definitely a better approach (those indexes can remain good even after relinking, while relative code addresses get changed).
You need some permanent identifier for each function. You save this identifier instead of function address and restore address after reading.
The simpliest is the integer identifier which is an index of array
const MathsOperation Operations[] = { &Add, &Sub };
In this case you must never change the order of Operations items.
If it is impossible, use strings:
const std::map<std::string, MathsOperation> OpNames
{
{ "Add", &Add },
{ "Sub", &Sub },
};

Initialize array of objects from a function (C++)

How do I initialize an array of objects from a function? I'm aware the code below is impractical; I'm just teaching myself C++.
Here is a structure that contains data.
struct pointStruct {
int numberPoints;
Point2D pointArray;
};
The Point2D class has instance variables x and y. In a separate function, I have:
void setPoints(void) {
pointStruct myPointData;
myPointData.numberPoints = 4;
myPointData.pointArray[4]; // here is the problem
// loop with i
myPointData.pointArray[i].x = ...;
myPointData.pointArray[i].y = ...;
}
I'm trying to initialize the array so that I can loop through it and set the x,y coordinates. I've tried using new and some other methods but I can't work through what I need to do. How can I fix this?
When I try to compile this code, I get the error "no match for 'operator[]' in 'myPointData.pointStruct::pointArray[4]' "
You should probably use std::vector like MadScienceDreams suggests.
However, if you want to learn about such things, you could use a pointer instead. For example:
struct pointStruct {
int numberPoints;
Point2D* pointArray;
};
void setPoints(void) {
pointStruct myPointData;
const int num_points = 4;
myPointData.numberPoints = num_points;
myPointData.pointArray = new Point2D[num_points];
for(int i = 0; i < num_points; ++i) {
myPointData.pointArray[i].x = ...;
myPointData.pointArray[i].y = ...;
}
// Do stuff with myPointData...
// Don't forget to have a "delete" for every "new" when you're done.
delete[] myPointData.pointArray;
}
Point2D pointArray;
pointArray is a single instance to Point2D. It is not an array of instances in which case it's type is Point2D [N].
myPointData.pointArray[4];
The above statement calls operator [] taking a parameter of type int, which is not you actually want. Since there is no such member function in Point2D, compiler complains. If you wish to create array of instances, use std::vector<Point2D>.

Are there some practical examples that use Object::*

I just heard of that there is a kind of type like this,a point to Object member. Here is it
class Point{float x, y;};
float Point::*p2 = &Point::x;
but I haven't use before,and wonder some-body really use it.Do you have any experience of that?
This is useful if you want to apply the same treatment to members without duplicating the code.
vector<Point> points; // suppose it has many elements
vector<double> Project(const vector<Point> points, int Point::* coord)
{
vector<double> result;
for (auto& p: points)
result.push_back(p.*coord);
return result;
}
// usage:
vector<double> Xs = Project(points, &Point::x);
vector<double> Ys = Project(points, &Point::y);
There are many other usages as well, for instance fast delegates (link).
Those are pointers to class members and are used for example to implement various functor classes (e.g.: boost::function or std::function).
http://en.cppreference.com/w/cpp/utility/functional/mem_fn
or
http://www.cplusplus.com/reference/std/functional/mem_fun/
class Point {
public: //public variables (can be accessed by outsider)
float x, y;
private: //private variables if you have any
};
Now to create an object you would do Point p, and you can access the elements by doing p.x and p.y, just like you would with a struct object.
If you want to create a class pointer, do Point *p, now if you want to access x, y, then you would do p->a and p->b. If you have another object Point t, and you want assign address of t to p, then you can do p = &t.

Passing pointer to 2D array c++

I'm having this problem for quite a long time - I have fixed sized 2D array as a class member.
class myClass
{
public:
void getpointeM(...??????...);
double * retpointM();
private:
double M[3][3];
};
int main()
{
myClass moo;
double *A[3][3];
moo.getpointM( A ); ???
A = moo.retpointM(); ???
}
I'd like to pass pointer to M matrix outside. It's probably very simple, but I just can't find the proper combination of & and * etc.
Thanks for help.
double *A[3][3]; is a 2-dimensional array of double *s. You want double (*A)[3][3];
.
Then, note that A and *A and **A all have the same address, just different types.
Making a typedef can simplify things:
typedef double d3x3[3][3];
This being C++, you should pass the variable by reference, not pointer:
void getpointeM( d3x3 &matrix );
Now you don't need to use parens in type names, and the compiler makes sure you're passing an array of the correct size.
Your intent is not clear. What is getpointeM supposed to do? Return a pointer to the internal matrix (through the parameter), or return a copy of the matrix?
To return a pointer, you can do this
// Pointer-based version
...
void getpointeM(double (**p)[3][3]) { *p = &M; }
...
int main() {
double (*A)[3][3];
moo.getpointM(&A);
}
// Reference-based version
...
void getpointeM(double (*&p)[3][3]) { p = &M; }
...
int main() {
double (*A)[3][3];
moo.getpointM(A);
}
For retpointM the declaration would look as follows
...
double (*retpointM())[3][3] { return &M; }
...
int main() {
double (*A)[3][3];
A = moo.retpointM();
}
This is rather difficult to read though. You can make it look a lot clearer if you use a typedef-name for your array type
typedef double M3x3[3][3];
In that case the above examples will transform into
// Pointer-based version
...
void getpointeM(M3x3 **p) { *p = &M; }
...
int main() {
M3x3 *A;
moo.getpointM(&A);
}
// Reference-based version
...
void getpointeM(M3x3 *&p) { p = &M; }
...
int main() {
double (*A)[3][3];
moo.getpointM(A);
}
// retpointM
...
M3x3 *retpointM() { return &M; }
...
int main() {
M3x3 *A;
A = moo.retpointM();
}
The short answer is that you can get a double * to the start of the array:
public:
double * getMatrix() { return &M[0][0]; }
Outside the class, though, you can't really trivially turn the double * into another 2D array directly, at least not in a pattern that I've seen used.
You could create a 2D array in main, though (double A[3][3]) and pass that in to a getPoint method, which could copy the values into the passed-in array. That would give you a copy, which might be what you want (instead of the original, modifiable, data). Downside is that you have to copy it, of course.
class myClass
{
public:
void getpointeM(double *A[3][3])
{
//Initialize array here
}
private:
double M[3][3];
};
int main()
{
myClass moo;
double *A[3][3];
moo.getpointM( A );
}
You may want to take the code in your main function which works with the 2D array of doubles, and move that into myClass as a member function. Not only would you not have to deal with the difficulty of passing a pointer for that 2D array, but code external to your class would no longer need to know the details of how your class implements A, since they would now be calling a function in myClass and letting that do the work. If, say, you later decided to allow variable dimensions of A and chose to replace the array with a vector of vectors, you wouldn't need to rewrite any calling code in order for it to work.
In your main() function:
double *A[3][3];
creates a 3x3 array of double* (or pointers to doubles). In other words, 9 x 32-bit contiguous words of memory to store 9 memory pointers.
There's no need to make a copy of this array in main() unless the class is going to be destroyed, and you still want to access this information. Instead, you can simply return a pointer to the start of this member array.
If you only want to return a pointer to an internal class member, you only really need a single pointer value in main():
double *A;
But, if you're passing this pointer to a function and you need the function to update its value, you need a double pointer (which will allow the function to return the real pointer value back to the caller:
double **A;
And inside getpointM() you can simply point A to the internal member (M):
getpointeM(double** A)
{
// Updated types to make the assignment compatible
// This code will make the return argument (A) point to the
// memory location (&) of the start of the 2-dimensional array
// (M[0][0]).
*A = &(M[0][0]);
}
Make M public instead of private. Since you want to allow access to M through a pointer, M is not encapsulated anyway.
struct myClass {
myClass() {
std::fill_n(&M[0][0], sizeof M / sizeof M[0][0], 0.0);
}
double M[3][3];
};
int main() {
myClass moo;
double (*A)[3] = moo.M;
double (&R)[3][3] = moo.M;
for (int r = 0; r != 3; ++r) {
for (int c = 0; c != 3; ++c) {
cout << A[r][c] << R[r][c] << ' ';
// notice A[r][c] and R[r][c] are the exact same object
// I'm using both to show you can use A and R identically
}
}
return 0;
}
I would, in general, prefer R over A because the all of the lengths are fixed (A could potentially point to a double[10][3] if that was a requirement) and the reference will usually lead to clearer code.