I'm working with OpenMp and I need to copy an instance of a class N times (one for each thread). I'm using inheritance to create my struct of data. For example:
// Super class
class vehicle {
private:
// general attributes of any vehicle
.......
}
// Sub class
class car : public vehicle {
private:
// some specific attributes of a car
string color;
......
public:
car(string color);
car(car _car);
void change_color(string color);
}
If I have 4 threads, I need to have 4 instance of the car but I would like that this 4 instances shares the same specific data of the super class (only one copy in memory). For example, if I have the follow code:
int main() {
.....
string colors[] = {"green", "blue", "red", "orange"};
.....
car base_car = new car(colors[0]);
car cars[4];
for ( int i = 0; i < 4; i++ ) {
cars[i] = new car(base_car);
}
....
int thread_id;
#pragma omp parallel private (thread_id)
thread_id = omp_get_thread_num();
car thread_car = cars[thread_id];
thread_car.change_color(colors[thread_id]);
}
I'd like that the instances of the car in the cars array share the attributes of the super class vehicle, that is to say, I would like to have only one copy of the data (in memory) of the attributes of the super class vheicle and 4 copy of the data of the derived class car.
This is possible?
Thank you.
Related
The crux of the issue is I want to create a vector of base pointers to reference children objects. However I'm having issues accessing the methods of the children. I've seen examples of downcasting online but I don't feel it's the best thing for me since I want to keep my code generic. Please look below for a sample of what I'm trying to accomplish.
class Base
{
public:
stuffx;
private:
stuffy;
}
template<typename U>
class Child : public Base
{
public:
Child(
std::function<U()> getterFunc,
std::function<void(U)> setterFunc
):
mgetter(getterFunc),
msetter(setterFunc)
{
}
U getFunction() const {return m_getter();}
void setFunction(U input) const {return m_setter(input);}
private:
observableValues() {}
std::function<U()> m_getter;
std::function<void(U)> m_setter;
}
int main()
{
std::vector<std::shared_ptr<Base>> Dummy = {std::make_shared<Child<int>> (std::bind(..), std::bind(...)),
std::make_shared<Child<string>> (std::bind(..), std::bind(...)) };
Dummy.at(0)->getGFunction(); // this throws an error as out of scope.
(dynamic_cast<Child<int>>(Dummy.at(0))->getGFunction(); // this is ok
}
In this example above my vector is of size 2 which is manageable but my goal is to serialize c++ classes to a psql server and may have to handle vectors of size 30+. My next question is is there a way to automate this in a for loop taking into the account the type deduction that may need to be performed for typename U.
int main()
{
std::vector<std::shared_ptr<Base>> Dummy = {std::make_shared<Child<int>> (std::bind(..), std::bind(...)),
std::make_shared<Child<string>> (std::bind(..), std::bind(...)) };
std::vector<std::shared_ptr<Base>>::const_iterator it_base = Dummy.begin();
for (; it_base != Dummy.end(); ++it_base)
{
//insert method here for downcasting
}
}
Record is a new feature in c#9, Net 5
It's said
If you want the whole object to be immutable and behave like a value, then you should consider declaring it as a record
Creating a record in c#9 , NET 5:
public record Rectangle
{
public int Width { get; init; }
public int Height { get; init; }
}
Then instantiating it:
var rectangle = new Rectangle (20,30);
Trying to change the value:
rectange.Width=50; //compiler error
Compiler raise the error:
error CS8852: Init-only property or indexer 'Rectangle.Width' can only be assigned in an object initializer, or on 'this' or 'base' in an instance constructor or an 'init' accessor.
That is right and insure that the record is immutable.
Using a method like to test IsImmutable type give false, because in record there is no generated readonly properties.
How to check the record in c# 9, Net 5 is immutable at runtime or even it has init property?
A record is indeed mutable at runtime. This is intentional, is it means most serializer frameworks work without updating.
It is however possible to check if a property is initonly by checking:
public static bool IsInitOnly(PropertyInfo propertyInfo)
{
return propertyInfo?.SetMethod.ReturnParameter
.GetRequiredCustomModifiers()
.Any(x => x.FullName == _isExternalInitName)
?? false;
}
private static string _isExternalInitName =
typeof(System.Runtime.CompilerServices.IsExternalInit).FullName;
I don't think that it's possible to check for immutability at runtime.
Here's some of the generated code for your record. You can see that both properties have a public setter.
public class Rectangle : IEquatable<Rectangle>
{
[CompilerGenerated]
private readonly int <Width>k__BackingField;
[CompilerGenerated]
private readonly int <Height>k__BackingField;
protected virtual Type EqualityContract
{
[CompilerGenerated]
get
{
return typeof(Rectangle);
}
}
public int Width
{
[CompilerGenerated]
get
{
return <Width>k__BackingField;
}
[CompilerGenerated]
set
{
<Width>k__BackingField = value;
}
}
public int Height
{
[CompilerGenerated]
get
{
return <Height>k__BackingField;
}
[CompilerGenerated]
set
{
<Height>k__BackingField = value;
}
}
The following code will compile and run without errors.
var rect = new Rectangle { Height = 1, Width = 2 };
typeof(Rectangle).GetProperty("Height").SetValue(rect, 5);
Console.Write(rect.Height);
//Prints 5
At runtime the init accessor is just a regular setter. It's only at compile time that a check is made to only allow init accessor to be called during object initialization.
So I don't see any way to check at runtime that Rectangle is immutable.
I am having a challenge calling methods from a direct parent Base class but I can call methods in the Base class 's parent with ease. To clarify what I mean here is the code:
First the structure of the opencascade library classes:
class TopoDS_Shape
{
public:
//..... a lot of methods like Closed(), Oriantable(), etc
};
class TopoDS_Face : public TopoDS_Shape
{
TopoDS_Face(); // implementation is like TopoDS_Face::TopoDS_Face(){}
}
In my code there are two types of topological faces Plane faces (ModelFace class) and NON-Planar faces (ModelBend class). These two faces share 6 attributes defined in the MFace class but only the ModelBend class has additional attributes of its own so I designed the system as follows
MFace class:
class MFace : public TopoDS_Face
{
FaceID mFaceID;
PlaneType mPlaneType;
FaceType mFaceType;
gp_Pnt mFaceNormal;
public:
void ModelFace::extractEdges()
{
for (TopExp_Explorer edgeEx((*this), TopAbs_EDGE); edgeEx.More(); edgeEx.Next())
{
TopoDS_Edge edge = TopoDS::Edge(edgeEx.Current());
ModelEdge edgex(edge);
addEdge(edgex);
}
}
// Setters and getters
// The OpenCascade Lib has a non-template method similar to this for converting a
// TopoDS_Shape to a face/edge/vertex/wire
template<typename T>
static T& toFace(TopoDS_Face& shape)
{
return *(T*) &shape;
}
};
ModelFace class:
class ModelFace : public MFace
{
ModelFace(); // implementation is like ModelFace::ModelFace(){}
void ModelFace::init(FaceID faceID) // WORKS LIKE A CHARM!!!
{
setFaceId(faceID);
std::cout << "ID : " << getFaceId() << '\n';
if (Closed()) {
std::cout << "Orr : " << Orientable() << '\n';
}
}
};
ModelBend class:
class ModelBend : public MFace
{
// Bend attributes : angles, radius, etc
ModelBend(); // implementation is like ModelBend::ModelBend(){}
// Setters and getters
// methods for computations
};
Usage : There is a Model class that represents a CAD model and stores all its topological ModelFace/ModelBend data. This class gets topological data in the form of a TopoDS_Shape and classifies it in the assignAttributes() as shown below :
void Model::assignFaceAttributes(const FaceID faceID, TopoDS_Shape& aShape)
{
// TODO : set the face attributes
TopoDS_Face pTopoDSFace = TopoDS::Face(aShape);
Standard_Real curvature = computeCurvature(pTopoDSFace);
if (curvature == 0.0){
std::cout << "Face" << '\n';
// Convert TopoDS_Face to ModelFace
ModelFace& pModelFace = MFace::toFace<ModelFace>(pTopoDSFace);
// This code work well : calls Orientable() in the TopoDS_Shape class
std::cout << "Orientable? : " << pModelFace.Orientable() << '\n';
// Works well
pModelFace.init(faceID);
// **PROGRAM CRASHES HERE!!!!!!!!!!!!!!**
pModelFace.extractEdges();
//...
} else {
// .....
std::cout << "Bend" << '\n';
// Convert TopoDS_Face to ModelBend
ModelBend& pModelFace = MFace::toFace<ModelBend>(pTopoDSFace);
//...
}
addFace(&pModelFace);
}
When I run the program it crashes on the call to pModelFace.extractEdges() in the assignAttributes() but when I copy the for loop in the extractEdges() method into the init() method it works fine.
My OOD/OOP ain't that good. May you please help me solve the problem and the why's of this behaviour. Thanks in advance.
This looks like a duplicate to your own other question:
Assigning a TopoDS_Face object to its child object compiles with no errors but I have 3 valgrind errors
TopoDS_Shape has no virtual methods (including no virtual destructor) and managed within OCCT by copy (e.g. not dynamically allocated). Adding class fields like you do in MFace will work only if you store object exactly like MFace - otherwise you are just casting a smaller in memory object TopoDS_Shape to a larger MFace leading to reading/writing to an uninitialized memory and crash.
The main difference between your MFace and TopoDS_Face is that TopoDS_Face defines NO new class fields nor virtual methods, which allows aliasing TopoDS_Shape to TopoDS_Face without side effects.
For instance:
void parseMFace (TopoDS_Shape& theFace)
{
MFace* anMFace = (MFace* )&theFace;
anMFace->doSomething();
}
int main()
{
MFace anMFace;
parseMFace (anMFace); // unsafe, but should work
TopoDS_Face aTFace;
parseMFace (aTFace); // will crash
TopoDS_Compound aComp;
BRep_Builder().MakeCompound (aComp);
BRep_Builder().Add (aComp, anMFace); // here MFace will be truncated to TopoDS_Shape
for (TopoDS_Iterator aFaceIter (aComp); aFaceIter.More(); aFaceIter.Next()
{
TopoDS_Face& aTFace2 = TopoDS::Face (aFaceIter.Value());
parseMFace (aTFace2); // will crash, because TopoDS_Compound does not store MFace
}
std::vector<MFace> anMFaces;
anMFaces.push_back (anMFace);
parseMFace (anMFaces[0]); // OK, but unsafe
}
Is it possible to initialize abstract base class' protected member for all derived objects without writing the same initializer list in all derived class constructors? So that it acts like a static member for all derived objects. What I want is something like this (except it doesn't work) Read it like a pseudo code:
A.h
class A {
public:
A(string fn);
virtual ~A();
virtual void open_file() = 0;
protected:
string fileName;
};
A.cpp
A::A(string fn) : fileName {fn} {} //Initializer list is written only once here
A::~A() {}
B.h
class B : public A {
public:
B();
~B();
void open_file() const override;
};
B.cpp
B::B() {} //No initializer list for A::fileName here
void B::open_file() const {
ifstream SomeFile(fileName); //Use base class' protected member
..... //Do some stuff with open file
}
And imagine there's also a C derived class without an initializer list for A here that has a different overriden open_file function..
main.cpp
string fname = {"foo.txt"};
A* APtr = new B(fname); //This initializes A's fileName for all derived objects as "foo.txt"
Aptr->open_file(); //B opens foo.txt
fname = "bar.txt";
A* A2Ptr = new C(fname); //Now fileName that both B and C consume is changed to "bar.txt"
A2Ptr->open_file(); //C opens bar.txt
APtr->open_file(); //B now opens bar.txt
You deklared the constructor from B: B(); but you try to use it A* APtr = new B(fname); So the compiler can't find any matching constructor.
initialize abstract base class' protected member for all derived objects without writing the same initializer list in all derived class
Why not?
A.hpp
class A
{
public:
A( string fn = "") : fileName(fn){} // you can give an default path if prefered.
};
B.hpp
class B : public A
{
public:
B( string fn = "") : A( fn ) {} //c++11 feature: call base constructor.
}
Other possible solutions were:
global variable (dirty and unsafe! - Please don't do it.)
static variable in A. But you can only open one file the same time.
give A setter and getter for fileName. And use it that way:
main.cpp
B* b = new B();
b->setFileName("foo.txt");
b->openFile();
I need helping trying to retrieve data held in a std::list<boost::shared_ptr<boost::any>>
I working on a Singleton Controller class with a private std::list. Client class(es) will be able to add/remove/edit concrete class objects to be used by the program through this Controller class.
The reason for using boost::shared_ptr is because I assign a unique objID to each concrete class created. Once instance objs are added to controller, user will be able to search and remove objs later. The Add(....) and Remove(...) overloaded methods for each concrete class work fine.
I am now trying to create getObject(int index) & setObject(int index) methods but can't seem to figure out how to cast the returned pointer to a Concrete class.
Please advise.
My current code:
//===============================================================
//Singleton.h controller class
private:
static Singleton *mgr;
typedef boost::shared_ptr<boost::any> Shapes_Ptr;
//private static list
static std::list<Shapes_Ptr> shapes;
public:
const Shapes_Ptr getObject( int index) const; //Return Shape
Shapes_Ptr EditObject( const int index ); //Edit Shape
Info(); //Prints contents of instance to console screen
//===============================================================
//Singleton.cpp
//Return Shape
const Shapes_Ptr getObject( int index) const
{
int cc = 0;
if ( (int)shapes.size() > ZERO && index < (int)shapes.size() )
{
list<Shapes_Ptr>::const_iterator i;
for ( i = shapes.begin(); i != shapes.end(); ++i )
{
if ( cc == index )
{
return (*i);
break;
}
else { ++cc; }
}//for-loop
}
}
//Edit Shape
Shapes_Ptr EditObject( const int index )
{
//same code as getObject()...
}
//===============================================================
//main.cpp
Singleton *contrl= Singleton::Instance();
int main()
{
for ( int i=0; i< 2; ++i )
{
contrl->CreateObject(Box2D() );
}
for ( int i = contrl->Begin(); i< contrl->End(); ++i )
{
if ( boost::any_cast<boost::any> (contrl->getObject(i)).type() == typeid(Physics::Box2D) )
{
//Code compiles but crashes on launch....
any_cast<Box2D> (contrl->getObject(i) ).Info(); // <== ERROR CODE
}
//More if checks for other Concrete classes....
}
}
Putting aside whatever the particular issue with your current code is, I think there is an issue with your design.
You have this Singleton manager class that acts as a sort of pool and also as you say assigns unique IDs to each object so they can be found later. But you know what lets code find objects? Pointers! If you use a normal pool, one per type hierarchy (so no more Boost Any), you may find it just as useful, and there will be less nasty if/else typeid-checking code (which everyone would agree is not a good use of RTTI, aside from being poor OOP).
So, what do you say? Chuck this, and use Boost Pool if you want something to allocate your objects from a central place, and use pointers as your unique IDs, thus avoiding lookups along the way.