No match for operator '=' - c++

Hi I'm a beginner C++ developer..I have a problem with a code that I post so it's easier to understand the problem.
Obj.h
class Obj : public QObject
{
Q_OBJECT
public:
typedef void (*factionState)();
struct Tran {
factionState Action;
unsigned int nextState;
};
void processAction(myState)
{
Tran const*t = myarrayAction + myState
*(t->action)();
myState=t->nextState;
}
private:
Tran const *myarrayAction;
unsigned int numStates;
protected:
myObj;
myState;
public:
Obj (Tran *arrayAction, const int nStates, const int i) {arrayAction=myarrayAction, numStates = nStates;};
void doNothing(){printf ("Do NOthing called\n")};
Obj_1.h
#include "Obj.h"
const int Obj_1=1
class Obj_1 : public Obj
{
private:
typedef enum {
OffState,
InitState,
RunState,
}state ;
static Obj::Tran myarrayAction[3];
public:
Obj_1() : Obj(myarrayAction, 3, Obj_1) {myState=OffState, myObj=Obj_1,init();};
private:
void init();
void GoToInitState();
void GoToRunState();
};
Obj_1.cpp
void Obj_1::init()
{
myarrayAction[3] = {
{&Obj::doNothing, OffState},
{&Obj_1::GoToInitState, InitState},
{&Obj_1::GoToRunState, RunState},
};
}
void Obj_1::GoToInitState()
{
// code;
}
void Obj_1::GoToRunState()
{
// code;
}
When I build the code I have this error:
no match for 'operator=' (operand types are 'Obj::Tran' and ''). So I tried to remove '=' and write Obj1::init like this
myarrayAction[3] {
{&Obj::doNothing, OffState},
{&Obj_1::GoToInitState, InitState},
{&Obj_1::GoToRunState, RunState},
};
But I have a sintax error..Any ideas??
Thanks

A couple of things. First, when Obj_1::init() executes, myarrayAction has already been initialized by the constructor. The { } syntax, which works for some array initializations, is not going to work here. You need an object (not a list of initializers) on the right-hand side of =.
Second, it looks like you want Obj_1::init() to set the contents of all three of the Obj::Tran objects within myarrayAction. But when you start a statement like this, myarrayAction[3] =, it is going to try to set the array member myarrayAction[3], that is, the fourth member of the array myarrayAction (whose first three members are myarrayAction[0], myarrayAction[1], myarrayAction[2]). But this array has only three members.
You are better off to write something like this:
myarrayAction[0] = ... ;
myarrayAction[1] = ... ;
myarrayAction[2] = ... ;
In the ... parts you call the constructors of the three objects you want to store at those three locations, passing the values you want to the parameters of each of these constructors.
Another thing you could do is, instead of using Obj::Tran* to represent an array of Obj::Tran, actually use a class to implement this array. If you know STL you could write std::vector<Obj::Tran>, for example. Or you could write your own class, depending on what you want. If you write a class, you can also write a constructor that takes the list of values you want as parameters, though you will not be able to organize them into sublists with nested { } as you could with an array initializer list.

Related

RAM-efficient C++ property

A property is a public data member of a class, which can be accessed by client code. And the owning object receives a notification (in the form of get/set notification callback) whenever the client code reads or modifies the property.
Some languages (like C#) have built-in properties.
I want to create a property for C++ that will be RAM-efficient.
The most obvious way to make a property is something like this:
class Super;
struct Prop {
Prop( Super * super ) : m_super(*super), m_a(0) {}
int operator=( int a );
operator int() const;
int m_a;
Super & m_super;
};
struct Super {
Super() : one(this), two(this) {}
void onSet() { printf("set"); }
void onGet() { printf("get"); }
Prop one;
Prop two;
};
int Prop::operator=( int a ) { m_super.onSet(); m_a = a; return a; }
Prop::operator int() const { m_super.onGet(); return m_a; }
Trouble is - every property has to keep a pointer to the outer class which I consider costly.
I want to know if there is a more RAM-efficient way to do this?
For example, if all Super-classes are generated, is it allowed by the Standard to get a pointer to the outer class from this pointer of the property?
Something like this:
struct Prop {
Prop( uint8_t offset ) : m_offset(offset), m_a(0) {}
int operator=( int a );
operator int() const;
int m_a;
const uint8_t m_offset;
};
int Prop::operator=( int a ) {
Super * super = (Super *)( ((char *)this) + m_offset);
super->onSet(); m_a = a; return a;
}
struct Super {
// assuming exact order of properties
Super() : one(0), two(sizeof(Prop)) {}
void onSet() { printf("set"); }
void onGet() { printf("get"); }
Prop one;
Prop two;
};
Since this offset is a constant expression it (theoretically) can be kept in ROM (or at least it can be smaller than sizeof(pointer)).
Or maybe there is another way?
c++ has properties as language extension
Look no further, msvc has support.
clang compiler also supports this syntax. Im not sure about gcc.
Storing offset can be also be done
Just, in the constructor calculate the offset from this, ala. :
Prop( Super& super ) {
uint8_t offset = this - std::addressof(super );//somewhat unmaintable - but may save some bytes
}
then when used, calculate back using this
Please note the space saving may be less than it seems due to alignment and padding.
I obviously don't know the context of your code, so this may be inconceivable in your specific implementation, but you could do something like
class Prop(){
Prop() : m_a(0){};
int operator=(int a){m_a = a;};
int m_a;
}
class Super(){
public:
int set_prop(int index, int value){
m_props[index] = value;
onSet();
return value;
}
private:
void onSet(){};
std::vector<Prop> m_props;
}
Obviously you need to initialize the vector and handle error cases etc but the logic is there - if you only access the props through the super.
That leaves you with purely the size of the sequence of structs with no pointers back to the super.

c++ iterating over member functions

I have a bit of a design problem:
I have a class describing a Robot; It can move to different directions, move a camera to different views etc. It looks something like this:
class Robot {
private:
...
public:
void move_right();
void move_left();
void switch_camera()
void raise_camera()
}
I want to add another method which performs a series of events. Thing is, I need able to abort the events midway.
I do want to clarify that the robot is running on a micro controller and not on a standard OS - so I can't really send a signal to the process or anything.
My first idea was to store the event functions in an array and iterate over it:
#typedef void(robo_event *)(void)
robo_event next_event;
robo_event *event_sequence;
Robot() {
this->next_event = nullptr;
}
void perform_event_series() {
for(this->next_event = *event_sequence; this->next_event != nullptr; this->next_event+=sizeof(robo_event)) {
this->next_event();
}
}
void abort_event_series() {
this->next_event = nullptr;
}
Thing is, the c++ standard forbids storing addresses of member functions, so this is starting to get awkward. I can make the functions static, but I do need to use them quite frequently and that would still be awkward. I want to be able to change to event sequence without too much work if changes are yet to come, so I thought that saving those on some sort of array / vector would be the best.
Any help with c++ member function syntax / better ideas on how to approach this problem would be much appreciated.
Thing is, the c++ standard forbids storing addresses of member functions
C++ most certainly allows you to store pointers to member functions (and variables), but the syntax is a bit different to accommodate the this pointer type, virtual functions, inheritance, etc.
class Example
{
public:
double foo(int x) { return x * 1.5; }
};
int main() {
double (Example::* member_function_ptr)(int);
member_function_ptr = &Example::foo;
Example example;
std::cout << (example.*member_function_ptr)(2) << std::endl;
}
If all your functions are for the same class, same return type, same arguments, etc. then you can make a table of them easy enough.
Storing pointers to member functions is perfectly allowable in c++:
#include <vector>
class Robot {
private:
public:
void move_right();
void move_left();
void switch_camera();
void raise_camera();
};
struct Action
{
Action(void (Robot::*what)(void))
: what(what)
{}
void perform(Robot& who) const
{
(who.*what)();
}
void (Robot::*what)(void);
};
bool should_abort();
void perform_actions(Robot& who, std::vector<Action> const& actions)
{
for (auto&& action : actions)
{
if (should_abort()) break;
action.perform(who);
}
}
int main()
{
std::vector<Action> actions {
&Robot::move_right,
&Robot::raise_camera,
&Robot::switch_camera,
&Robot::move_left
};
Robot r;
perform_actions(r, actions);
}
Pointers to functions are of different types to pointers to members.
You need void(Robot::*)(void) not void(*)(void).
class Robot {
private:
typedef void(Robot::*robot_event)(void)
robo_event next_event;
robo_event *event_sequence;
Robot() {
next_event = nullptr;
}
void perform_event_series() {
for(next_event = *event_sequence; next_event != nullptr; ++next_event) {
(this->*next_event)();
}
}
void abort_event_series() {
next_event = nullptr;
}
public:
void move_right();
void move_left();
void switch_camera()
void raise_camera()
}

Impossible to store cocos2d::Animation * in a std::vector of structure?

I work on a project made with cocos2d-x framework (c++).
In my Player class, I have to manage the animations.
Iinitially I had this code that worked without any problem:
First, the animation object is a cocos2d Class cocos2d::Animation. Just remember that this object contains a cocos2d::Vector<AnimationFrame*> _frames; member.
Doc: http://www.cocos2d-x.org/reference/native-cpp/V3.5/d3/dc5/classcocos2d_1_1_animation.html#a0fdc0be158df7e09d04644be353db056
class Player : public cocos2d::Sprite {
private:
cocos2d::Map<std::string, cocos2d::Animation*> animations;
cocos2d::Vector<cocos2d::SpriteFrame*> getAnimation(const char *format, int frameStart, int count);
void update(float delta) override;
bool init() override;
public:
static Player* create();
bool init() override;
//...
};
And the implementation side:
bool Player::init() {
//...
animations.insert("idleN", Animation::createWithSpriteFrames(getAnimation("%04d", 207, 9), 0.1));
//...
}
Vector<SpriteFrame*> Player::getAnimation(const char *format, int frameStart, int count) {
auto spriteCache = SpriteFrameCache::getInstance();
Vector<SpriteFrame*> animFrames;
char str[100] = {0};
for (int i = 1; i <= count; i++)
{
sprintf(str, format, frameStart);
log("%s", str);
animFrames.pushBack(spriteCache->getSpriteFrameByName(str));
frameStart++;
}
return animFrames;
}
//later in the code execution
void Player::manageIdle() {
auto idleAnim = Animate::create(animations[0].anim);
runAction(idleAnim);
}
You can see each Animation is contained in cocos2d::Map<std::string, cocos2d::Animation*> and as I say before, this code worked perfectly, no error.
But I needed some more informations in addition to the name and the object itself so I decided to use a structure to store all infos for each animation. And I replaced the cocos2d::Map<std::string, cocos2d::Animation*> by std::vector<animData> with animData as structure. I refactored the code like so:
class Player : public cocos2d::Sprite {
public:
typedef struct animation {
std::string name;
cocos2d::Animation* anim;
//all others info needed, not relevant here, (just several enum type variables)
} animData;
private:
std::vector<animData > animations; //the new container
//rest of code stay unchanged
};
The changes in the implementation side:
bool Player::init() {
//...
animations.push_back({"idleN", Animation::createWithSpriteFrames(getAnimation("%04d", 207, 9), 0.1)});
//no problem here...
}
But now, when I try to create a new anim with a animation saved in my container (vector) I get a SegV on this line:
void Player::manageIdle() {
auto idleAnim = Animate::create(animations[0].anim); //SegV here, in Animate::create() funct
runAction(idleAnim);
}
After search, I find that each structure member anim which is type of cocos2d::Animation*, now conatains a empty cocos2d::Vector<AnimationFrame*> _frames; and there is the problem !
It’s as if they lose the cocos2d::Vector<AnimationFrame*> ref or something like that.
So my question is why cocos2d::Vector<AnimationFrame*> become empty with my refactored code and not whith the previous one ?
I found this with test like that:
auto test = animList[0].anim->getFrames();
if (test.empty()) {
log("empty"); //The test output empty
}
Debugguer screen in the end of the init() funct:
Debugguer screen in Player::manageIdle() funct:
Edit: when I add animations.back().anim->retain(); right after the line to add an element in the vector, it solves the problem !
animations.push_back({"idleN", Animation::createWithSpriteFrames(getAnimation("%04d", 207, 9), 0.1)});
animations.back().anim->retain();
Because cocos2d::Animation* inherit from cocos2d::Ref, it is an auto-release object. When used inside a cocos2d container like cocos2d::Map or cocos2d::Vector, it is auto managed by the container itself. But I use a std::vector so I lose the ref I think. Something like that.
Now I need to find a way to get rid of this additional line of code because this multiple by twice my number of line here !
So new question here: How I can get rid of the fact I have to call animations.back().anim->retain(); each time I add a new element in my vector ?
You might create a wrapper around Ref, which "retains" ownership, and store this wrapper instead, sort of a std::unique_ptr e.g.
template<typename T> class RefOwner {
public:
RefOwner(T *t) : ref(t) {
ref->retain();
}
~RefOwner() {
ref->release();
}
T *operator->() { return ref; }
private:
T *ref;
};
and then use it as
struct animData {
std::string name;
RefOwner<cocos2d::Animation> anim;
//all others info needed, not relevant here, (just several enum type variables)
};
Disclaimer: I have no experience with cocos2d-x, just looked at Animation and Ref

call C++ member function from the string input format

suppose i have a simple C++ class :
class Calc
{
private:
int a;
public:
Calc(){
a = 0;
}
void seta(int a){
this->a = a;
}
int geta(){
return a;
}
};
Now, suppose, in main i create a object of this class, and take two inputs from user : var_name which is name of instance variable in string format, and action which is set or get in string format. For ex : if var_name = "a" and action == "get" , then i should be able to call geta() fn. Is there any way to achieve this in C++.
pls dont provide if..then..else kind of soln. I want to write a generic code which need not be updated as more members are added in class Calc.
You cannot dynamically modify C++ types. However, it sounds like you just want a way to set and read attributes. You don't need to modify your class structure for this, there are other alternative solutions. For example you could use an std::map:
class Calc
{
private:
std::map<std::string, int> attributes;
public:
Calc(){}
void setAttr(const std::string& name, int value){
attributes[name] = value;
}
int getAttr(const std::string& name){
return attributes[name];
}
};

Cannot assign element std::array directly, it says no operator "=" matches

In my processor class there is an array <Job, 10>.
void Processor::addJob(Job job) {
this->Jobs[this->uBound] = job;
this->uBound++;
}
I'd like to add a new element inside my processor class. to do that i create new private: int uBound = 0 property in my processor class. and I assign directly this->Jobs[this->uBound] = job;. it gives me an error. it says Error : no operator "=" matches these operands. operand types are: std::array<Job, 10U> = Job.
so I tried to use this->Job->assign(Job); it assigned to all elements of my Jobs, but I just wanted only one element.
here the class of Job
class Job {
public:
string name;
public :
int length = 0;
public:
bool used = false;
public:
Job();
public:
Job(string n, int l);
~Job();
};
and here the Processor class
class Processor {
private:
int turnArround_time = 0;
private:
int uBound = 0;
public:
std::array<Job, 10> *Jobs = new std::array<Job, 10>();
public:
Processor();
public:
void addJob(Job job);
public:
int getTurnArround();
~Processor();
};
I have no idea what does the error mean.
Is there any alternative way to add Job object to Processor->Jobs ?
any help appreciated, thanks...
The correct syntax will look like
( *this->Jobs )[this->uBound] = job;
Though it is not clear why the array is allocated dynamically.
Of course you also could write for example :)
this->Jobs[0][this->uBound] = job;
but it only confuses the reader of the code.