I'm trying to modify a bool field in a method. The method accepts a pointer pointer bool, but can't seem to figure it out how to do this correctly.
This is a basic example of something similar I want to do:
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning(&seenWarningA)
}
void pushWarning(bool ** warning) {
**warning = true;
}
}
This code example errors (sending bool* but needs to be bool**) and I've tried other ways with no luck. Can't find any online examples but maybe I'm searching for the wrong terms. What is the right way to do this?
Since you have a class, no parameters are required.
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning()
}
void pushWarning() {
seenWarningA = true;
}
}
Using references rather than pointers is more elegant.
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning(seenWarningA)
}
void pushWarning(bool & warning) {
warning = true;
}
}
If you want to use pointers, the & operator just gives single pointer rather than a double point:
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning(&seenWarningA)
}
void pushWarning(bool * warning) {
*warning = true;
}
}
You appear to be trying to pass an argument of bool* into a function that takes bool**. Remove one of the layers of indirection from the parameter list, or add one to the value you're passing in. Either should work.
Two mistakes:
First- your declaration of pushWarning is with parameter of type bool**, and you are trying to send bool*.
Second- you can simply use reference:
using namespace std;
class WarningManager {
public:
bool seenWarningA;
void updateWarnings() {
pushWarning(seenWarningA);
}
void pushWarning(bool &warning) { // You can simply use refference instead of pointer to pointer, or pointer at all..
warning = true;
}
};
int main()
{
WarningManager w;
w.seenWarningA = false;
w.updateWarnings();
cout << w.seenWarningA; // Prints 1
return 0;
}
Related
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()
}
I have a vector populated with callback functions and I would like to check whether callback to the function already exists prior to adding it. I don't know whether it will even work bu so far it doesn't even compile.
vector<std::function<void(void*)>> _callbacks;
void Event::RegisterCallback(std::function<void(void*)> callback)
{
if (callback == NULL)
return;
vector<std::function<void(void*)>>::iterator it = std::find(_callbacks.begin(), _callbacks.end(), callback);
if (it == _callbacks.end())
{
_callbacks.push_back(callback);
}
else
{
//print error
throw;
}
}
This gives a compile error:
"Overload resolution selected deleted operator '=='" in alorithm(805). This is related to the find function call.
How do I get this to work and is it even going to compare function calls to the same method properly?
Thanks
As noted in the comments the simplest solution is to use default C-style function pointers as they support == operator in opposite to C++11 function which does not.
using func_type = void(*)();
vector<func_type> _callbacks;
void Event::RegisterCallback(func_type callback)
{
if (callback == nullptr)
return;
auto it = std::find(_callbacks.begin(), _callbacks.end(), callback);
if (it == _callbacks.end()) {
_callbacks.push_back(callback);
}
else {
throw;
}
}
void f() {};
void g() {};
/*
evt.RegisterCallback(f); // works fine
evt.RegisterCallback(g); // works fine
evt.RegisterCallback(f); // throws exception
*/
If you don't like this approach you can write your own function-pointer class with support of equality operator.
Another solution is to have a class with a std::function member and another comperable member, and then overloading the () to get the std::function parameter and call it with the parameter, and the == operator to compeare the class using the comperable member.
CompareableFunction.h:
class CompareableFunction
{
public:
CompareableFunction(int nId, std::function<void(parameter)> handler);
~CompareableFunction();
void operator()(parameter param);
bool operator== (CompareableFunction compareableFunc);
private:
std::function<void(parameter)> m_handler;
int m_nId;
};
CompareableFunction.cpp:
CompareableFunction::CompareableFunction(int nId, std::function<void(parameter)> handler)
{
m_nId = nId;
m_handler = handler;
}
CompareableFunction::~CompareableFunction()
{
}
void CompareableFunction::operator()(parameter param)
{
return m_handler(param);
}
bool CompareableFunction::operator==(CompareableFunction compareableFunc)
{
return (m_nId == compareableFunc.m_nId);
}
EDIT: you can convert the std::function to a C-style function pointer and use it to compare. example to a conversion is here: http://www.cplusplus.com/forum/general/63552/
To avoid code duplication, I'm tring to pass pointers to functions as arguments of a static method.
I have a class (Geo) with only static methods. One of this methods (+++Geo::traceRay(+++)) should just display(Geo::display(+++)) few things, then return an int.
Another class (Las) needs to use the Geo::traceRay(+++) method, but should display(Las::display(+++)) someting else.
So I try to pass a pointer to function argument to the Geo::traceRay(+++, pointer to function) method. the pointed functon will the right "display()" method.
Up to now, passing the first pointer to display() is not an issue, but I can't find how to do it with the second one.
class Geo
{
public:
static bool display(int pix);
static int traceRay(int start, int end, bool (*func)(int) = &Geo::display); // no issue with this default parameter
};
class Las
{
public:
bool display(int pix);
void run();
};
int Geo::traceRay(int start, int end, bool (*func)(int))
{
for (int i = start; i < end ; ++i )
{
if((*func)(i)) return i;
}
return end;
}
bool Geo::display(int pix)
{
cout << pix*100 << endl;
return false;
}
bool Las::display(int pix)
{
cout << pix << endl;
if (pix == 6) return true;
return false;
}
void Las::run()
{
bool (Las::*myPointerToFunc)(int) = &display; // I can just use display as a non member class, but it should stay a member
Geo::traceRay(0,10, myPointerToFunc); // issue here!
}
int main()
{
Geo::traceRay(0,10); // use the "normal display" = the default one// OK
Las myLas;
myLas.run();
return 0;
}
You can't pass a member function pointer as a function pointer. I presume making Las::display static is not an option. In that case, I would suggest taking a std::function and using std::bind to bind the current instance:
static int traceRay(int start, int end, std::function<bool(int)> func = &Geo::display);
...
Geo::traceRay(0,10, std::bind(&Las::display, this, std::placeholders::_1));
Also, in both cases, you can call func by:
func(i);
No need to dereference it first.
What Chris suggests is great if that's as far as it goes.
Another approach to this, which would be beneficial if you have several shared functions like that, would be to use an interface (with a virtual method Display(+++)) with two implementations, put an instance of the implementation in question in each of Geo and Las (or Las could directly implement the interface). Then traceRay takes a reference to the interface base class and calls the display method on it.
I'm busy with making a leveleditor class in an engine but I'm stuck at passing a member function as parameter of another member function.
First I've made a typedef
typedef void (LevelEditor::*CallFunctionPtr)();
Then I have made a member function to check if the user clicks with his mouse on a hitregion. If so, another function needs to be called. So I've my first member function with 2 parameters
LevelEditor.h
void CheckClickCollision(HitRegion* region, CallFunctionPtr callFunctionPtr);
LevelEditor.cpp
void LevelEditor::CheckClickCollision( HitRegion* region, CallFunctionPtr callFunctionPtr)
{
if(GAME_ENGINE->GetLButtonMouseState())
{
if(!m_bIsLeftPressed && region->HitTest(m_MousePosition))
(this->*callFunction)();
m_bIsLeftPressed = true;
}
else
m_bIsLeftPressed = false;
}
Then I've two stupid example member functions:
LevelEditor.h
void LevelUp();
void LevelDown();
LevelEditor.cpp
void LevelEditor::LevelUp()
{
++m_iCurrentLevel;
}
void LevelEditor::LevelDown()
{
if(m_iCurrentLevel > 0)
--m_iCurrentLevel;
else
return;
}
And now I want to call that function every tick to check if there is a hit. So in my tick function:
CheckClickCollision(m_LeftArrowRegionPtr, LevelDown);
CheckClickCollision(m_RightArrowRegionPtr, LevelUp);
And here I get the error on LevelDown and Levelup:
Error: argument of type void (LevelEditor::*)()" is incompatible with parameter of type "CallFunctionPtr *"
Dont know how to fix it. Tried different things, nothing worked
Try
CheckClickCollision(m_LeftArrowRegionPtr, &LevelEditor::LevelDown);
CheckClickCollision(m_RightArrowRegionPtr, &LevelEditor::LevelUp);
For your convenience, here's the working sample (the compiler is GCC 4.7):
#include <stdio.h>
class LevelEditor;
typedef void (LevelEditor::*CallFunctionPtr)();
class LevelEditor
{
public:
LevelEditor() {}
void CheckClickCollision(void* region, CallFunctionPtr callFunction)
{
(this->*callFunction)();
}
void LevelUp() { printf("up\n"); }
void LevelDown() { printf("down\n"); }
void Test()
{
CheckClickCollision(NULL, &LevelEditor::LevelDown);
CheckClickCollision(NULL, &LevelEditor::LevelUp);
}
};
int main()
{
LevelEditor e;
e.Test();
return 0;
}
The other way to call this:
void Test()
{
CallFunctionPtr p;
p = &LevelEditor::LevelDown;
CheckClickCollision(NULL, p);
p = &LevelEditor::LevelUp;
CheckClickCollision(NULL, p);
}
You need to use std::function and std::bind, or lambdas if you have a supporting compiler.
void LevelEditor::CheckClickCollision( HitRegion* region, std::function<void()> callFunction)
{
if(GAME_ENGINE->GetLButtonMouseState())
{
if(!m_bIsLeftPressed && region->HitTest(m_MousePosition))
callFunction();
m_bIsLeftPressed = true;
}
else
m_bIsLeftPressed = false;
}
void Test()
{
// lambda
CheckClickCollision(NULL, [this] { LevelDown(); });
// bind
CheckClickCollision(NULL, std::bind(&LevelEditor::LevelDown, this));
}
I have defined the classes 'Outcome' and 'Bin'.
I am trying to pass an array of type Outcome to a Bin Constructor, in order to add each element of that array to a set of 'Outcome's that is a member property of the Bin Class.
//Bin.h
class Bin {
private:
std::set<Outcome> outcomeset;
public:
Bin();
Bin(Outcome Outcs[], int numberofelements);
Bin(std::set<Outcome> Outcs);
void add(Outcome Outc);
std::string read();
};
//In Bin.cpp
Bin::Bin(Outcome outcs[], int numberofelements) {
int i;
for (i=0;i<(numberofelements-1);i++) {
outcomeset.insert(outcs[i]); //When this LIne is commented out, no compile errors!
}
}
This results in a whole mess of errors in VS2010 that link back to library files. I have been unable to find anything online or in my "The Big C++" textbook. Is this a completely wrong implementation of this sort of functionality? Or am I missing something rather basic?
For the curious I am implementing this as part of the 'Roulette' Problem from this free textbook http://www.itmaybeahack.com/homepage/books/oodesign.html
Thanks for your help!
EDIT: I have added the (rather lengthy) error text to a pastebin, here: http://pastebin.com/cqe0KF3K
EDIT2: I have implemented the == != and < operators for the outcome class, and the same line still does not compile. Here are the implementations
//Outcome.cpp
bool Outcome::operator==(Outcome compoutc) {
if (mEqual(compoutc) == true) {
return true;
}
else {
return false;
}
}
bool Outcome::operator!=(Outcome compoutc) {
if (mEqual(compoutc) == false) {
return true;
}
else {
return false;
}
}
bool Outcome::operator<(Outcome compoutc) {
if (odds < compoutc.odds) {
return true;
}
else {
return false;
}
}
EDIT3: Implemented the comparison operator with the de-referenced parameter and const tags and now it compiles!
You need to define an operator< for the class being inserted into the set.
Also note that instead of an explicit loop, you're probably better off using a pair of "iterators" (pointers, in this case) and actually initializing the set:
#include <set>
#include <string>
class Outcome {
int val;
public:
bool operator<(Outcome const &other) const {
return val < other.val;
}
Outcome(int v = 0) : val(v) {}
};
class Bin {
private:
std::set<Outcome> outcomeset;
public:
Bin();
// Actually initialize the set:
Bin(Outcome Outcs[], int n) : outcomeset(Outcs, Outcs+n) {}
Bin(std::set<Outcome> Outcs);
void add(Outcome Outc);
std::string read();
};
int main() {
// Create an array of Outcomes
Outcome outcomes[] = {Outcome(0), Outcome(1) };
// use them to initialize the bin:
Bin b((outcomes),2);
return 0;
}