How do I call function in another functions parameters? - c++

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);

Related

Why cast a function call with no return to void?

I was reading through a code base and saw this code:
void some_function()
{
...
}
a_type some_other_function()
{
...
(void) some_function();
...
}
Why is this? Some way to make the code more readable?

Checking same if condition to series of functions

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();

Avoid if-else statement with template function

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.

How to pass a function as parameter

I have two methods that are mostly the same, so I'm thinking of refactoring them.
A simple version is:
void C::GetEmailAlerts(set<AlertPtr>& alertSet)
{
...
...
AlertPtr pAlert = Cache::Get()->GetAlert();
for (...) {
...
if (pAlert->isEmail())
alertSet.insert(p);
}
...
}
void C::GetMobileAlerts(set<AlertPtr>& alertSet)
{
...
...
AlertPtr pAlert = Cache::Get()->GetAlert();
for (...) {
...
if (pAlert->isMobile())
alertSet.insert(p);
}
...
}
Is it possible to make it like:
void C::GetAlerts(set<AlertPtr>& alertSet, ??? func) // How to pass a function as parameter?
{
...
...
AlertPtr pAlert = Cache::Get()->GetAlert();
for (...) {
...
if (pAlert->func())
alertSet.insert(p);
}
...
}
so that I just call:
C c;
c.GetAlerts(emailSet, isEmail);
c.GetAlerts(mobileSet, isMobile);
------------------------ EDIT -----------------------
Maybe a generic example is easier to demonstrate what I would like to have:
#include <iostream>
using namespace std;
struct A
{
int foo() { cout<<"in foo()"<<endl; }
int bar() { cout<<"in bar()"<<endl; }
};
A *instance = new A();
struct C
{
public:
void test1()
{
instance->foo();
}
void test2()
{
instance->bar();
}
// void test(???) // How to pass member function as a pointer?
// {
// instance->f();
// }
};
int main()
{
C c;
c.test1();
c.test2();
// c.test(&A::foo);
// c.test(&A::bar);
return 0;
}
In this second example, I'd like to use c.test(&A::foo); to replace c.test1(), and maybe c.test2, c.test3, ...
Is there a clean way to do this?
Well, depends. If you are using C++11, you can use the auto type and then execute the parameter. Otherwise, you'd need to know if the function is an int, void, char, etc. and then execute the given parameter.
If isEmail like this: bool AlertPtr::isEmail(), you should use the below code:
void C::GetAlerts(set<AlertPtr>& alertSet, bool (AlertPtr::*func)())
{
...
...
AlertPtr pAlert = Cache::Get()->GetAlert();
for (...) {
...
if (pAlert->func)
alertSet.insert(p);
}
...
}
Why not cascading your if (pAlert->isMobile()) and if (pAlert->isEmail()) in the same function?
Using function pointer to deal with this problem seems way overengineering.
void C::GetAlerts(set<AlertPtr>& emailAlertSet, set<AlertPtr>& mobileAlertSet)
{
...
...
AlertPtr pAlert = Cache::Get()->GetAlert();
for (...) {
...
if (pAlert->isEmail()) {
emailAlertSet.insert(p);
else if (pAlert->isMobile()) {
mobileAlertSet.insert(p);
}
}
...
}
Is very simple just use namespaces define each of them in a namespace and can easily access them with the scoop operator
For who might interested, I finally figured out how to do it:
void C::GetAlerts(set<AlertPtr>& alertSet, bool (AlertClass::func)())
{
...
if ((pAlert->*func)())
...
}
This is how we call this function:
C c;
c.GetAlerts(emailSet, &AlertClass::isEmail);
c.GetAlerts(mobileSet, &AlertClass::isMobile);
Full solution for the second example:
#include <functional>
#include <iostream>
using namespace std;
struct A
{
int foo() { cout<<"in foo()"<<endl; }
int bar() { cout<<"in bar()"<<endl; }
};
A *instance = new A();
struct C
{
public:
void testFoo()
{
instance->foo();
}
void testBar()
{
instance->bar();
}
void test(int (A::*p)())
{
(instance->*p)();
}
};
int main()
{
C c;
c.testFoo();
c.testBar();
c.test(&A::foo);
c.test(&A::bar);
return 0;
}

Passing a member function as parameter of a member function

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));
}