lambdas as instance function pointers - c++

my type aButton has a function pointer so i can define custom actions for each button, i though the easiest way to do this would be to create a lambda and dereference it and pass it to the function pointer of that aButton instance, since i need non-static access to objects outside of the scope of the button class
but i'm stuck trying to figure out how to cast it to the right type and how to call it without getting the errors below... i haven't see many people have luck with this, and using functional doesn't look like i can pass in context???
// Example program
#include <iostream>
#include <string>
int global1 = 0;
int global2 = 5;
class aButton {
public:
int status, oldStatus;
aButton(int initStatus) { oldStatus = status = initStatus; }
int (aButton::*action)();
};
class Thingy {
private:
int mode = 1;
int value = 0;
public:
void reset() { value = 0; }
void setMode(int newMode) { mode = newMode; }
void increment() { value = value + global2; }
//accessors & mutators
};
void specialFunction(Thingy *thingyToWorkOn) {
//do stuff...
}
void anotherSpecialFunction(Thingy *firstThingy, Thingy *secondThingy) {
//more stuff...
}
int main() {
Thingy one;
Thingy two;
aButton *on = new aButton(0);
aButton *speedUp = new aButton(0);
on->action = &( //error: taking address of temporary [-fpermissive]
[&]() { //error: cannot convert 'main()::<lambda()>*' to 'int (aButton::*)()' in assignment
//some specific stuff....
global1 = 1;
if (global2 < 10) {
global2++;
}
one.reset();
two.reset();
anotherSpecialFunction(&one, &two);
std::cout << "on action \n";
return 1;
}
);
speedUp->action = &( //error: taking address of temporary [-fpermissive]
[&]() { //error: cannot convert 'main()::<lambda()>*' to 'int (aButton::*)()' in assignment
//some specific stuff....
if (global1) {
one.setMode(global2);
two.setMode(global2);
specialFunction(&one);
specialFunction(&two);
std::cout << "speedUp action \n";
return 1;
}
return 0;
}
);
for(int i=0; i<5; i++) {
//if on pushed
(on->(on->action))(); //error: expected unqualified-id before '(
//if speedUp pushed
(speedUp->(speedUp->action))(); //error: expected unqualified-id before '(
}
}

I believe that you want aButton::action to be of type std::function<int()> (read: function that takes nothing and returns int) rather than int (aButton::*). This requires the <functional> header. With that change, your assignments could stay the same (minus the leading address-of operator), though as you figured out, you'll need to explicitly state the return type with -> int. The calls would simply take the form (e.g.):
on->action();
One other note: be very careful about capturing local variables (one, two) by reference. If the function really is main then I suppose it's ok since main won't return until the program ends, but otherwise it would be asking for trouble.

You cannot assign pointer to lambda to pointer to member function. Pointers to member functions may point only to member functions.
You can indeed use std::function from <functional> instead. Declare your action as
std::function<int()> action;
so instead of using member functions you will use global functions. Of course you need to get rid of & operators for lambdas. And you need to modify the way of calling action.

Thanks guys, i guess functional was what i was looking for after all... this seems to do what i want on http://cpp.sh/8ll i guess i just got confused cause a lot of the functional examples had them as arguments for callbacks instead
// Example program
#include <iostream>
#include <string>
#include <functional>
int global1 = 0;
int global2 = 5;
class aButton {
public:
int status, oldStatus;
aButton(int initStatus) { oldStatus = status = initStatus; }
std::function<int()> action;
};
class Thingy {
private:
int mode = 1;
int value = 0;
public:
void reset() { value = 0; }
void setMode(int newMode) { mode = newMode; }
void increment() { value = value + global2; }
//...
};
void specialFunction(Thingy *thingyToWorkOn) {
//do stuff...
}
void anotherSpecialFunction(Thingy *firstThingy, Thingy *secondThingy) {
//more stuff...
}
int main() {
Thingy one;
Thingy two;
aButton *on = new aButton(0);
aButton *speedUp = new aButton(0);
on->action = std::function<int()>(
[&]() -> int{
//some specific stuff....
global1 = 1;
if (global2 < 10) {
global2++;
}
one.reset();
two.reset();
anotherSpecialFunction(&one, &two);
std::cout << "on action \n";
return 1;
}
);
speedUp->action = std::function<int()>(
[&]() -> int{
//some specific stuff....
if (global1) {
one.setMode(global2);
two.setMode(global2);
specialFunction(&one);
specialFunction(&two);
std::cout << "speedUp action \n";
return 1;
}
return 0;
}
);
for(int i=0; i<5; i++) {
//if on pushed
on->action();
//if speedUp pushed
speedUp->action();
}
}

Related

C++ GetAsyncKeyState() with private overridden attributes

I am trying to figure out how to use GetAsyncKeyState with private attributes forward and backwards from a base class. I need to be able to reset GetAsyncKeyState to other keypresses. Any idea?
Maybe overriding forward and backwards with other keypresses?
#include <iostream>
#include <windows.h>
#include <string>
#include<conio.h>
using namespace std;
bool reset_defaults = false;
class Base {
protected: // OR private
int forward = VK_UP, backwards = VK_DOWN;
public: //...
}
////////////
class Move : public Base {
public:
Base def;
int move() {
while (true) {
if (GetAsyncKeyState(forward) < 0){
cout << ("forward >>>\n");
if (GetAsyncKeyState(forward) == 0){
cout << ("Stopped\n");
}
}
if (GetAsyncKeyState(VK_SPACE) < 0){break;}
}
}
int main() {
Move move;
move.move();
}
Sorry, but I don't think I understand the whole logic of this yet.
PS UPDATE:
How can I override baseKeys values:
class MovementKeys {
protected:
int baseKeys(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right){
default_key_forward = VK_UP;
default_key_backward = VK_DOWN;
default_key_left = VK_LEFT;
default_key_right = VK_RIGHT;
}
public:
int definedCommand(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right) {
while (reset_defaults == false)
{
cout << ("HERE 1 \n");
if (GetAsyncKeyState(default_key_forward) < 0)
{
cout << ("forward\n");
}
if (GetAsyncKeyState(default_key_backward) < 0)
{
court << ("backwards\n");
}
if (GetAsyncKeyState(default_key_left) < 0)
{
cout << ("left\n");
}
if (GetAsyncKeyState(default_key_right) < 0)
{
cout << ("right\n");
}
if (GetAsyncKeyState(VK_SPACE) < 0) { break; }
}
return 0;
}
int derived_newKeys(int default_key_forward, int default_key_backward, int default_key_left, int default_key_right) {
return baseKeys(default_key_forward, default_key_backward, default_key_left, default_key_right);
}
You probably want to use member variables to store the keys. Instead of deriving the class with new keys, you set the variables in constructors (to default or to changed values) and can also change the key assignment later on.
You probably want to create a separate class, which reacts on the events.
#include <iostream>
#include <windows.h>
#include <conio.h>
using namespace std;
class World {
public:
void forward() { y--; };
void backward() { y++; };
void left() { x--; };
void right() { x++; };
private:
int x = 0;
int y = 0;
};
class MovementKeys {
// member variables
private:
// keep reference to world instead of copy; main() has to make sure World object outlives MovementKeys object
World& world;
int key_forward;
int key_backward;
int key_left;
int key_right;
public:
// constructor, which only sets world, but keeps the keys at their default settings
//
// world has to be initialized before the constructor function body
// as references have no default value
// put initialization in member initialization list
MovementKeys(World& w) : world(w)
{
key_forward = VK_UP;
key_backward = VK_DOWN;
key_left = VK_LEFT;
key_right = VK_RIGHT;
}
// constructor which modifies keys
MovementKeys(World& w, int change_key_forward, int change_key_backward, int change_key_left, int change_key_right) : world(w)
{
changeKeys(change_key_forward, change_key_backward, change_key_left, change_key_right);
}
// command loop controlled by keys
int definedCommand()
{
while (true)
{
cout << ("HERE 1 \n");
if (GetAsyncKeyState(key_forward) < 0)
{
cout << ("forward\n");
world.forward();
}
if (GetAsyncKeyState(key_backward) < 0)
{
cout << ("backwards\n");
world.backward();
}
if (GetAsyncKeyState(key_left) < 0)
{
cout << ("left\n");
world.left();
}
if (GetAsyncKeyState(key_right) < 0)
{
cout << ("right\n");
world.right();
}
// optionally change keys from within while loop
if (GetAsyncKeyState(VK_BACK) < 0)
{
key_forward = VK_RETURN;
}
if (GetAsyncKeyState(VK_SPACE) < 0)
{
break;
}
}
return 0;
}
// function for changing the keys stored in the member variables
// can be called by constructor or externally
void changeKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right)
{
key_forward = change_key_forward;
key_backward = change_key_backward;
key_left = change_key_left;
key_right = change_key_right;
}
};
int main()
{
World earth;
// use default keys, declares local variable and constructs MovementKeys object called move
MovementKeys move(earth);
move.definedCommand();
// use custom keys, share same world, declares local variable and constructs MovementKeys object called move2
// static_cast<int>() with a letter in a literal char parameter works, because the VK_ values of letter keys are the actual ASCII values (on purpose by Microsoft, I would assume)
MovementKeys move2(earth, static_cast<int>('W'), static_cast<int>('S'), static_cast<int>('A'), static_cast<int>('D'));
move2.definedCommand();
// change keys in move2
move2.changeKeys(VK_LBUTTON, VK_RBUTTON, VK_CONTROL, VK_SHIFT);
move2.definedCommand();
// run first one again for the fun of it
move.definedCommand();
}
Alternatively passing World& only, where it is used in definedCommand (and at the same time be able to use several worlds):
class World {
// ...
};
class MovementKeys {
// member variables without world, we can also put default value here
private:
int key_forward = VK_UP;
int key_backward = VK_DOWN;
int key_left = VK_LEFT;
int key_right = VK_RIGHT;
public:
// default constructor with no parameters, delegate to other constructor
// delegating not necessary, as the default values are set above anyway; just demonstrating various techniques for initializing member variables
MovementKeys() : MovementKeys(VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT) {};
// constructor which modifies keys, put everything in member initialization list
MovementKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right) : key_forward(change_key_forward), key_backward(change_key_backward), key_left(change_key_left), key_right(change_key_right) {};
// command loop controlled by keys, pass World& here as parameter
int definedCommand(World& world)
{
while (true)
{
// ...
}
return 0;
}
void changeKeys(int change_key_forward, int change_key_backward, int change_key_left, int change_key_right)
{
// ...
}
};
int main()
{
// use default keys, declares local variable and constructs MovementKeys object called move
MovementKeys move;
// use custom keys, declares local variable and constructs MovementKeys object called move2
MovementKeys move2(static_cast<int>('W'), static_cast<int>('S'), static_cast<int>('A'), static_cast<int>('D'));
MovementKeys defaultMenuKeys;
World earth;
World moon;
World menu; // between moving in worlds, we want to control some settings in a menu
move.definedCommand(earth);
move2.definedCommand(earth);
move2.definedCommand(moon);
// change keys in move2
move2.changeKeys(VK_LBUTTON, VK_RBUTTON, VK_CONTROL, VK_SHIFT);
move2.definedCommand(earth);
defaultMenuKeys.definedCommand(menu);
// run first one again for the fun of it
move.definedCommand(moon);
}
You can introduce a (class) enum with a list of the states, why definedCommand() returns:
// outside or can be put into MovementKeys and henceforth used as MovementKeys::ReturnReason
class enum ReturnReason { EXIT, NEWKEYS, SHOWMENU, SWITCHWORLD };
// in class MovementKeys
ReturnReason definedCommand() {
// ...
return NEWKEYS;
// ...
return EXIT;
// ...
return SHOWMENU;
// ...
}
// in main()
ReturnReason r = definedCommand();
if (r == NEWKEYS)
move2.changeKeys(...);
else if (r == EXIT)
return 0;
If you use that 'trick' to also control the menu, it could make sense to use virtual inheritance now for World. As the normal World and the menu World probably react quite differently. (The base class (ancestor) would be World, which is recognized by MovementKeys. Your actual Worlds are objects of derived (children) classes, with more specific behaviour.
definedCommand then can be called and run with any derived class of the base class World.

C++ Derived Class Override Return Type

I think my example below will explain what I am trying to do. I know that I cannot override the return type of the eval() function unless they are covariants, so obviously I am doing something wrong. My question: how do I have a polymorphic base class and derived classes which can evaluate themselves in different ways?
#include <iostream>
class Node {
public:
virtual void eval() = 0;
};
class IntNode: public Node {
public:
IntNode() { val = 0; }
IntNode(int i) { val = i; }
int eval() { return val; }
private:
int val;
};
class FloatNode: public Node {
public:
FloatNode() { val = 0; }
FloatNode(float i) { val = i; }
float eval() { return val; }
private:
float val;
};
int main() {
Node *a = new IntNode(5);
Node *b = new FloatNode(2.3);
std::cout << a->eval() << std::endl;
std::cout << b->eval() << std::endl;
return 0;
}
EDIT: Resolved
Thank you all for the suggestions. I have figured out a way to accomplish my ultimate goal. In the end I wanted a polymorphic symbol table. I used some of your ideas to get this to work. The biggest breakthrough was to do this "double-sided" plus function. To add two Vars, the first asks the other to add the other with the first's value:
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
class Var {
public:
virtual void print() = 0;
virtual Var *plus(int i) = 0;
virtual Var *plus(float f) = 0;
virtual Var *plus(Var *other) = 0;
};
class IntVar: public Var {
public:
// constructors
IntVar();
IntVar(int i);
void print();
// operations
Var *plus(int i);
Var *plus(float f);
Var *plus(Var *other);
private:
int val;
};
class FloatVar: public Var {
public:
// constructors
FloatVar();
FloatVar(float f);
void print();
// operations
Var *plus(int i);
Var *plus(float f);
Var *plus(Var *other);
private:
float val;
};
// constructors
IntVar::IntVar() { val = 0; }
IntVar::IntVar(int i) { val = i; }
void IntVar::print() { cout << "" << val << endl; }
// operations
Var *IntVar::plus(int i) { return new IntVar(i+val); }
Var *IntVar::plus(float f) { return new FloatVar(f+val); }
Var *IntVar::plus(Var *other) { return other->plus(val); }
// constructors
FloatVar::FloatVar() { val = 0; }
FloatVar::FloatVar(float f) { val = f; }
void FloatVar::print() { cout << "" << val << endl; }
// operations
Var *FloatVar::plus(int i) { return new FloatVar(i+val); }
Var *FloatVar::plus(float f) { return new FloatVar(f+val); }
Var *FloatVar::plus(Var *other) { return other->plus(val); }
int main() {
unordered_map<string, Var *> symbol_table;
symbol_table["a"] = new IntVar(5);
symbol_table["b"] = new FloatVar(2.3);
symbol_table["c"] = symbol_table["a"]->plus(symbol_table["b"]);
symbol_table["a"]->print();
symbol_table["b"]->print();
symbol_table["c"]->print();
return 0;
}
A simple answer is you can not. Overrides in in C++ has to return the same type as original function.
However, a more sophisticated answer is you can, with some tricks. One of the tricks would be to use type-erased return value, for example, through std::any - see more on it's usage on https://en.cppreference.com/w/cpp/utility/any
With std::any, functions can return any value they want, but it would be type-erased - so callers would have to know what to do with this return value... Which, in a sense, severely limits the applicability scope of this solution. However, there is a place for this as well.
You cannot.
The static type of an expression cannot depend on the dynamic type of an object. Take for instance:
auto f(Node& n) { return n.eval(); }
What is the type of f?
You could resolve your issue with std::variant but it would mean the base class knows all types children class could return. This is really a design issue, and you should fix it.

Change class variable after finding

I am currently working on a chess engine in C++, and in the engine, I'm trying to modify a string variable "piece" inside of a class "ChessTile" within another class called "ChessBoard".
Anyways when I use a function to return a class, then modify said class, it doesn't change the source variable, and I was wondering how you do that.
Here is a simple script I wrote to demonstrate:
#include <iostream>
#include <string>
class child {
private:
int myVar;
public:
child(int v) {
myVar = v;
}
int getVar() {
return myVar;
}
int setVar(int Svar) {
this->myVar = Svar;
return 0;
}
};
class parent {
public:
child baby = child(0);
child findMyChild(int var) {
if (var == 1) {
return baby;
}
}
};
parent DAD;
int main() {
std::cout << DAD.findMyChild(1).getVar() << std::endl;
DAD.findMyChild(1).setVar(50);
std::cout << DAD.findMyChild(1).getVar() << std::endl;
}
The output for this is:
0
0
But I'm wanting it to be:
0
50
If necessary, I can also post my chess engine. Thank you!
In your code, findMyChild() is returning a copy of the baby ( function returning by value), use return by reference instead like so.
child& parent::findMyChild(int var) {
if (var == 1)
{
return baby;
}
/* other codes */
return baby;
}
You are returning a copy of child in findMyChild. Therefore, you modify only that copy, not the member itself.
You should return a pointer to the member
child* findMyChild(int var) {
return var == 1
? &baby
: nullptr;
}
then dereference it to get/set its value. For example:
DAD.findMyChild(1)->setVar(50);
Since findMyChild can return null pointer in my code you should check its existence before accessing
child* c = DAD.findMyChild(1);
if (c) c->setVar(50);
You can do it via returning pointer/reference of child as stated by another comment or you can do it via an interface in parent class.
#include <iostream>
#include <string>
#define FIRST_CHILD 1
#define CANNOT_FIND_CHILD -1
class child {
private:
int myVar;
public:
child(int v) {
myVar = v;
}
int childGetVar() {
return myVar;
}
int childSetVar(int Svar) {
this->myVar = Svar;
return 0;
}
};
class parent {
public:
child baby = child(0);
int getVar(int var) {
if (var == FIRST_CHILD)
return baby.childGetVar();
return CANNOT_FIND_CHILD;
}
int setVar(int var, int Svar) {
if (var == FIRST_CHILD)
baby.childSetVar(Svar);
return CANNOT_FIND_CHILD;
}
};
parent DAD;
int main() {
std::cout << DAD.getVar(FIRST_CHILD) << std::endl;
DAD.setVar(FIRST_CHILD, 50);
std::cout << DAD.getVar(FIRST_CHILD) << std::endl;
}

How does lambda capture member of a struct

My code goes like this :
struct foo {
int first;
int second;
};
void func(foo& A) {
Schedule([=]()
{
DoWork(A.first, A.second)
});
}
Does lambda capture the reference to the struct by value or does it capture the .first and and .second by value ?
Thanks,
Take the following code:
#include <iostream>
using namespace std;
class NeedDeepCopy
{
public:
NeedDeepCopy()
{
};
NeedDeepCopy(const NeedDeepCopy& other)
{
data = new int[1];
data[0] = 0x90;
}
int *data;
};
void func(NeedDeepCopy& obj) {
auto lambda = [=]() mutable
{
if(*obj.data == 0x90)
cout << "0x90 - a copy was made";
};
if(*obj.data == 0x88)
cout << "Original value is 0x88" << endl;
lambda();
}
int main() {
NeedDeepCopy obj;
obj.data = new int[1];
*obj.data = 0x88;
func(obj);
// your code goes here
return 0;
}
http://ideone.com/Ws6KJX
The answer is: a copy to the entire object / structure is made. In case you're dealing with objects which need a deep copy, you need to pay attention otherwise you might get uninitialized data.
By value, if you want to capture by ref it is [&]
If you want to capture a by value and b by ref you put [a,&b]

Getting crash while calling a function which need reference to vector

I want to know is there something wrong in passing in passing vector reference to a function as in the example below. This code is running well and nice. But the same type of code in my project gives me crash. I don't know why.
In that case whenever I calls the function which need std::vector & . then in the called function the size of the vector reaches some millionsss.... I have attached screenshot where I am actually getting this crash.
I just wants to know is there something wrong in these type of implementations...
#include <iostream>
#include <vector>
#include <string>
class A {
public:
A() {}
~A() {}
void GetVector(std::vector<std::wstring> &in) {
std::wstring s = L"Hello";
for(int i = 0; i < 10; i++)
in.push_back(s);
}
};
class B {
public:
B() {}
~B() {}
void GetData() {
A a;
std::vector<std::wstring> s;
a.GetVector(s);
}
};
int main() {
B b;
b.GetData();
return 0;
}
Real code where I am getting the crash...
void SCPreferenceComp::PopulateComboBox()
{
SCConfig *config = SCConfig::GetInstance();
std::vector<std::wstring> languages;
config->GetAllLangugesName(languages);
for(size_t i = 0; i != languages.size(); i++)
mLangListComboBox->addItem(languages[i].c_str(), i+1);
if(mLangListComboBox->getNumItems() > 0)
mLangListComboBox->setSelectedId(1);
}
bool SCConfig::GetAllLangugesName(std::vector<std::wstring> &outLangNames)
{
bool retVal = false;
do
{
if(!mXMLDoc)
break;
xercesc::DOMNodeList *langNodeList = mXMLDoc->getElementsByTagName(strToX("language"));
if(!langNodeList)
break;
const XMLSize_t langCount = langNodeList->getLength();
for(XMLSize_t i = 0; i < langCount; i++)
{
xercesc::DOMNode *curLangNode = langNodeList->item(i);
if(!curLangNode)
continue;
xercesc::DOMElement *curLangElem = dynamic_cast<xercesc::DOMElement*>(curLangNode);
if(!curLangElem)
continue;
wxString s = strToW(curLangElem->getAttribute(strToX("name")));
outLangNames.push_back(s.c_str());
}
retVal = true;
}while(false);
return retVal;
}
I can't see anything wrong in that implementation other than the fact that it doesn't have any visible end result which leads me to believe it may not exactly match your failing code.