lets say for example i have the following code:
bool foo1() {
check something...
}
void foo2() {
do something ...
}
void foo3() {
do something ...
}
void foo4() {
do something ...
}
void foo5() {
do something ...
}
void foo6() {
if (foo1()) foo2();
if (foo1()) foo3();
if (foo1()) foo4();
if (foo1()) foo5();
}
is there a better way to do this? i don't want to write the if statement every time, but each of the other functions might change the calculation of foo1().
i have a series of different functions and i want it to use foo1() before every call.
You could put the functions in a container and then use a loop:
std::vector<void (*)()> functions = {foo2, foo3, foo4, foo5};
for (auto f: functions)
if (foo1())
f();
Related
Can I call functions in function parameters?
void Function_1() {
//some code
}
void Function_2(void* Using_Function()) {
//some code
Using_Function();
//some code
}
int main() {
Function_2(Function_1);
return 0;
}
Is it even possible to do so?
I think you are asking about function pointers, if so then like this.
void Function_1() {
//some code
}
void Function_2(void (*Using_Function)()) {
//some code
Using_Function();
//some code
}
...
Function_2(Function_1);
Well, all I want to do is a "switch" with a function pointer, but with methods pointers. The switch is that if I call the method Run(), it will either redirect to A::RunOn() or A::RunOff() according to Run ptr is pointing to these member functions.
I know it can be done. I did it in plain c but I have searched and googled to do the same thing in c++ but no luck.
class A
{
typedef (void)(A::*RunPtr)(int);
RunPtr RunMethod;
public:
RunMethod Run;
A()
{
Run = RunOff;
}
void SetOn(bool value)
{
if (value)
Run = RunOn;
else
Run = RunOff;
}
void RunOn(int)
{
// RunOn stuff here
}
void RunOff(int)
{
// RunOff stuff here
}
};
So I can call Run() and there will be a switch between the function calls, which I think is more efficient than just doing:
if (on)
RunOn();
else
RunOff();
Don't know how to do it!
Your member function pointer typedef is wrong (Despite the other issues in the shown code). You need
typedef void(A::*RunPtr)(int);
Or you can provide the alias for the member function pointer of class A with the help of using keyword as follows:
using RunPtr = void(A::*)(int);
RunPtr RunMethod;
Now in the SetOn you can do member pointer assignment as follows
void SetOn(bool value)
{
RunMethod = value ? &A::RunOn : &A::RunOff;
}
Now, in order to call the stored member function pointer, you may/ can provide a Run member function as follows:
void Run(int arg)
{
std::invoke(RunMethod, this, arg);
// do something...
}
The call to member function is a bit tricky.
However, this can be done using more generic std::invoke from <functional> header (Since c++17).
Here is the complete example:
#include <iostream>
#include <functional> // std::invoke
class A
{
using RunPtr = void(A::*)(int);
// or with typedef
// typedef void(A::*RunPtr)(int);
RunPtr RunMethod;
public:
void SetOn(bool value)
{
RunMethod = value ? &A::RunOn : &A::RunOff;
}
void Run(int arg)
{
std::invoke(RunMethod, this, arg);
// do something...
}
void RunOn(int arg) { std::cout << "RunOn: " << arg << "\n"; }
void RunOff(int arg) { std::cout << "RunOff: " << arg << "\n"; }
};
int main()
{
A obj;
obj.SetOn(true);
obj.Run(1); // prints: RunOn: 1
obj.SetOn(false);
obj.Run(0); // prints: RunOff: 0
}
(See a Demo)
Your code works fine once you fix the syntax mistakes in it, namely:
Class needs to be class.
in RunMethod Run;, RunMethod is not a type, it is a member variable. You meant to use RunPtr Run; instead (and get rid of RunMethod), but that won't work so well for you (see further below for why).
in Run = RunOn; and Run = RunOff;, you need to fully qualify the method name, and prefix it with the & operator, eg Run = &A::RunOn;.
Try the following:
class A {
public:
typedef void (A::*RunPtr)(int);
RunPtr Run;
A()
{
Run = &A::RunOff;
}
void SetOn(bool value)
{
if (value)
Run = &A::RunOn;
else
Run = &A::RunOff;
}
void RunOn(int param)
{
//RunOn stuff here
}
void RunOff(int param)
{
//RunOff stuff here
}
};
Note, however, that even though you can use Run as a public method pointer like this, the caller will still need to use operator.* or operator->* to actually call it, and that would not look so nice, eg:
A a;
(a.*a.Run)(...);
Online Demo
If you want to be able to call Run() like a.Run(...) then you have to make Run() be a standard method, and have it use a method pointer internally, eg:
class A {
typedef void (A::*RunPtr)(int);
RunPtr RunMethod;
public:
A()
{
RunMethod = &A::RunOff;
}
void SetOn(bool value)
{
if (value)
RunMethod = &A::RunOn;
else
RunMethod = &A::RunOff;
}
void RunOn(int param)
{
//RunOn stuff here
cout << "RunOn: " << param << endl;
}
void RunOff(int param)
{
//RunOff stuff here
cout << "RunOff: " << param << endl;
}
void Run(int param)
{
(this->*RunMethod)(param);
}
};
A a;
a.Run(...);
Online Demo
I want to have objects with one method which calls a function (but every object should have a different function to call). I will try to show you what I mean by showing an example:
class Human
{
public:
void setMyFunction(void func); // specify which function to call
void callMyFunction(); // Call the specified function
};
void Human::setMyFunction(void func) // ''
{
myFunction = func;
}
void Human::callMyFunction() // ''
{
myFunction();
}
void someRandomFunction() // A random function
{
// Some random code
}
int main()
{
Human Lisa; // Create Object
Lisa.setMyFunction(); // Set the function for that object
Lisa.callMyFunction(); // Call the function specified earlier
}
This code (obviously) doesn't work but I hope you understand what I am trying to accomplish.
MfG, TPRammus
You might use std::function.
#include <functional>
class Human
{
std::function<void()> mFunc;
public:
void setMyFunction(std::function<void()> func) { mFunc = func; }
void callMyFunction() { if (mFunc) mFunc(); }
};
Demo
I would suggest using a simple function pointer. Just do this:
class Human
{
public:
using func_t = void (*)();
void setMyFunction(func_t f) {
func = f;
}
void callMyFunction() {
func();
}
private:
func_t func;
};
The reasons why one might prefer function pointers to std::function are:
Performance. Calling std::function tends to be slower, than calling a function by pointer.
std::function needs truly ugly syntax when one needs to bind it to an overloaded function.
Example:
void foo();
void foo(int x = 0);
void check() {
Human h;
h.setMyFunction(&foo);
}
Will fail to compile.
If I have some code like this:
void function_1(...)
{
//do something
}
void function_2(...)
{
//do something
}
int function_3(...)
{
//do something
}
int main()
{
....
if (CONSTANT_1) function_1()
else if (CONSTANT_2) function_2()
else if (CONSTANT_3) function_3()
....
}
I would like avoid the if-else statement and do something like this in main function:
int main()
{
function<CONSTANT>();
}
How can I avoid the use of if-else statement and simulate this behavior?
In general you can specialize the function template:
template<int N>
void function();
template<>
void function<1>()
{
//do something
}
template<>
void function<2>()
{
//do something
}
template<>
void function<3>()
{
//do something
}
This works, but there might be better solutions as well.
Overload and tag dispatch. The Base template will convert the constant into a unique type. Then simple overload resolution will choose the proper overload. This is all assuming the constant are constexpr, and not something known only at run-time.
void function(std::integral_constant<int, CONSTANT_1>)
{
//do something
}
void function(std::integral_constant<int, CONSTANT_2>)
{
//do something
}
int function(std::integral_constant<int, CONSTANT_3>)
{
//do something
}
template<int constant>
auto function()
{
return function(std::integral_constant<int, constant>{});
}
int main()
{
function<CONSTANT_2>(); // calls the second overload
}
The above has the benefit of issuing a compile time error when an overload isn't found, as opposed to a linkage error if you specialize template functions instead.
Alright, in my main i have:
void somefunction();
int main()
{
//bla bla bla
SomeClass myclass = SomeClass();
void(*pointerfunc)() = somefunction;
myclass.addThingy(pointerfunc);
//then later i do
myclass.actionWithDiffrentOutcomes();
}
void somefunction()
{
//some code
}
and in the class:
class SomeClass()
{
public:
void addThingy(void (*function)());
void actionWithDiffrentOutcomes();
private:
std::vector<void (**)()> vectoroffunctions;
}
SomeClass::addThingy(void (*function)())
{
vectoroffunctions.push_back(&function);
}
SomeClass::actionWithDiffrentOutcomes()
{
(*vectoroffunctions[0])();;
}
I'm sort of new-ish to pointers, but I read over my c++ books, googled, ext. and this seems correct, compiles, runs but when I call "actionWithDiffrentOutcomes()" I get an access violation. I'm not sure what to do. it seems correct, but something is obviously wrong. So how can I call a function from within a class when the definition is in another?
I'm doing it this way because i cannot hard-code every option into a switch statement.
Your code is almost correct. Your vector is mistakenly holding pointers to pointers to functions rather than simply pointers to functions. addThingy is adding the address of the function pointer in to the vector, but that pointer goes out of scope in the next line.
Change your code as follows:
//Store pointers to functions, rather than
//pointers to pointers to functions
std::vector<void (*)()> vectoroffunctions;
SomeClass::addThingy(void (*function)())
{
//Don't take the address of the address:
vectoroffunctions.push_back(function);
}
Also, you have a lot of syntax errors in the rest of the code which should stop the code from even compiling.
The problem is here:
vectoroffunctions.push_back(&function);
You're adding address of the local variable. The local variable gets destroyed once you return from the function. The address which the vector stores points to a destroyed object which is why you get "access violation" error at runtime.
To fix this, do this:
First change this
std::vector<void (**)()> vectoroffunctions;
to this:
std::vector<void (*)()> _functions; //vector of function-pointer-type
//I changed the name also!
which is practically same as:
std::vector<void()> _functions; //vector of function-type
Now do this:
_functions.push_back(function); //add copy!
To make it more flexible, you could use template along with std::function as:
class A
{
public:
template<typename Function>
void add(Function && fn)
{
_functions.push_back(std::forward<Function>(fn));
}
void invoke_all()
{
for(auto && fn : _functions)
fn();
}
private:
std::vector<std::function<void()>> _functions;
};
Now you can use it to store functions as well as functors:
void myfunction() { std::cout << "myfunction" << std::endl ; }
struct myfunctor
{
void operator()() { std::cout << "myfunctor" << std::endl ; }
};
A a;
a.add(myfunction); //add function
a.add(myfunctor()); //add functor!
a.invoke_all();
Output (Online Demo):
myfunction
myfunctor
Hope that helps.
Function pointers are much more legible with typedefs:
typedef void (*RequiredFunction)();
Then you can declare addThingy() like this:
void addThingy(RequiredFunction function);
And vectoroffunctions like so:
std::vector<RequiredFunction> vectoroffunctions;
The definition of addThingy will be:
void SomeClass::addThingy(RequiredFunction function)
{
vectoroffunctions.push_back(function);
}
And your main() would look more like:
int main()
{
SomeClass sc;
RequiredFunction pointerfunc = somefunction;
sc.addThingy(pointerfunc);
sc.actionWithDiffrentOutcomes();
}
Far fewer *s and &s with which to make mistakes!