I want to be able to return a function from a class, so that I do not need to if-else through a return type.
I have a class that returns multiple strings. Instead, I want to return multiple functions.
#include <iostream>
class Handler
{
private:
public:
int handleMessage(int code)
{
return code+1;
}
};
void func1();
void func2();
void func3();
int main (int argc, char *argv[])
{
Handler handle;
int code = handle.handleMessage(0);
if(code == 1)
{
func1();
}
return 0;
}
void func1(){ std::cout << "1" << std::endl;}
void func2(){ std::cout << "2" << std::endl;}
void func3(){ std::cout << "3" << std::endl;}
What I want is: That the function handleMessage in the class Handler returns something so that in my main application I do not have to use if-else.
So the main looks like this:
function = handle.handleMessage(0);
And the application will choose which function it will run.
for example:
function = handle.handleMessage(0); //will run func1
function = handle.handleMessage(1); //will run func2
You can modify the member function such that it returns a function pointer, e.g.
using fptr = void (*)();
struct Handler
{
fptr handleMessage (int code)
{
if (code == 0)
return &func1;
else if (code == 1)
return &func2;
else
return &func3;
}
};
This can be invoked as follows
Handler handle;
auto f = handle.handleMessage(0);
f();
Note that the above if-else if-else dispatch isn't ideal. Prefer a data member that stores the function pointers and associates them with a code, e.g. using a std::unordered_map.
Note that when you need to return stateful function objects in the future, this approach will fail. Then, you need to embrace std::function which is able to wrap lambdas with closures or custom types with an operator() overload.
There are several ways to do so, the simplest one, you can use an std::function. In this example we returning a lambda function for each case. You can replace it with the functions you just wrote.
class Handler {
public:
std::function<void()> handleMessage(int code) {
code = code + 1; // ++code or whatever
if (code == X) {
return []() { std::cout << "Cool! I'am x!" << std::endl; };
} else if (code == Y) {
return []() { std::cout << "Cool! I'am x!" << std::endl; };
} else if (...) {
...
} else {
....
}
}
};
Then your main function becomes:
int main (int argc, char *argv[]) {
Handler handle;
const auto func = handle.handleMessage(0);
func();
return 0;
}
You can replace the swith/if case statement by an array storing the different functions, like they mentioned in the comments.
If you dont want to pay the extra virtual function call regarding the usage of an std::function, you can use an alias like the answer below or just the auto keyword:
class Handler {
public:
constexpr auto handleMessage(int code) {
code = code + 1; // ++code or whatever
if (code == X) {
return &func1;
} else if (code == Y) {
return &func2;
} else if (...) {
...
} else {
....
}
}
};
std::function is a powerful tool. The tiny brother is a simple function pointer.
I transformed MCVE respectively to return a function pointer:
#include <iostream>
typedef void (*FuncPtr)();
void func1();
void func2();
void func3();
void funcError();
class Handler
{
private:
public:
FuncPtr handleMessage(int code)
{
switch (code + 1) {
case 1: return &func1;
case 2: return &func2;
case 3: return &func3;
default: return &funcError;
}
}
};
int main (int argc, char *argv[])
{
Handler handle;
FuncPtr pFunc = handle.handleMessage(0);
pFunc();
return 0;
}
void func1(){ std::cout << "1" << std::endl;}
void func2(){ std::cout << "2" << std::endl;}
void func3(){ std::cout << "3" << std::endl;}
void funcError(){ std::cout << "ERROR!" << std::endl;}
Output:
1
Live Demo on coliru
You can return a function with return_type(*function_name)(argument_type1, argument_type2...) so a function that looks like:
double f(int a, int b);
has the name double(*f)(int, int).
Worth mentioning is C++11's std::function which requires the <functional> header. It has a more intuitive usage: std::function<double(int, int)> but also adds a bit of overhead.
I would also like to suggest the usage of C++17's std::optional as for the case when the variable code goes out of bounds. This implementation requires the <optional> header.
std::optional<void(*)()> handleMessage(int code){
switch (code) {
case 0: return std::optional(func1);
case 1: return std::optional(func2);
case 2: return std::optional(func3);
}
return std::nullopt; //empty
}
usage in main looks like the following:
Handler handle;
auto func = handle.handleMessage(0);
if (func.has_value()) {
func.value()();
}
as this allows to check if func.has_value() which is quite convenient.
Use an array of functions.
void func1(){ std::cout << "1" << std::endl; }
void func2(){ std::cout << "2" << std::endl; }
void func3(){ std::cout << "3" << std::endl; }
typedef void (* func ) () ;
class Handler {
public:
func handleMessage(int code)const{
static const func F[] = { func1, func2, func3 };
return F[ code ];
}
};
int main()
{
Handler handler;
func f = handler.handleMessage(0); // returns func1
f();
}
live example
you can map the ints to a function or lambda, but read befor what at() does and what happens if the key is not found!!
void function1()
{
std::cout << "q1" << std::endl;
}
void function2()
{
std::cout << "q2" << std::endl;
}
int main(int argc, char* argv[])
{
std::map<int, std::function<void(void)>> map;
map.insert(std::make_pair(1, function1));
map.insert(std::make_pair(1, function2));
map.at(1)();
I would like to offer solution without any if-else block. You just need to templatize your Handler::handleMessage function. Something like this:
// Class declaration
class Handler
{
private:
public:
template<int code>
void handleMessage();
};
and specialize the function template for particular codes:
// Function template specializations.
template<>
void Handler::handleMessage<1>()
{
std::cout << "1" << std::endl;
}
template<>
void Handler::handleMessage<2>()
{
std::cout << "2" << std::endl;;
}
template<>
void Handler::handleMessage<3>()
{
std::cout << "3" << std::endl;;
}
// All cases, except 1, 2 and 3
template<int code>
void Handler::handleMessage()
{
std::cout << "Anything else" << std::endl;;
}
The usage may look like:
Handler h;
h.handleMessage<1>(); // Prints 1
h.handleMessage<2>(); // Prints 2
h.handleMessage<3>(); // Prints 3
h.handleMessage<323>(); // Prints 'Anything else'
Related
Does this code architecture cause memory leakage by not freeing m_func?
And could this be tempered with if this code would be executed at a closed server? Like finding the address of the pointer and replacing the code of the function pointee with malicious code? If so how could I solve this?
#include <iostream>
template <typename Func>
struct endpoint_t {
void* m_func;
endpoint_t(Func&& func) : m_func((void*) func) {}
auto execute() {
return ((Func*) m_func)();
}
};
int hello_world() {
std::cout << "Hello World! \n";
return 0;
}
int main() {
endpoint_t end(hello_world);
end.execute();
}
Edit:
This is the actual goal of the code: To store multiple endpoint functions inside a vector.
#include <vector>
#include <iostream>
template <typename Func>
struct endpoint_t {
void* m_func;
endpoint_t(Func&& func) : m_func((void*) func) {}
auto execute() {
return ((Func*) m_func)();
}
};
int hello_world() {
std::cout << "Hello World! \n";
return 0;
}
int hello_world2() {
std::cout << "Hello World 2! \n";
return 0;
}
int main() {
std::vector<endpoint_t<???>> array;
array.push_back(hello_world);
array.push_back(hello_world2);
}
Assuming the prototypes of all your 'hello world' functions is the same (int return value, no parameter), you don't need templates at all. Just store a function pointer.
typedef int (*Func_t)();
int hello_world() {
std::cout << "Hello World! \n";
return 0;
}
int hello_world2() {
std::cout << "Hello World 2! \n";
return 0;
}
int main() {
std::vector<Func_t> array;
array.push_back(&hello_world);
array.push_back(&hello_world2);
}
Assuming that the prototypes do differ, it becomes a wee bit more difficult, but not very much so, thanks to std::function.
int hello_world() {
std::cout << "Hello World! \n";
return 0;
}
int hello_world2(int value) {
std::cout << "Hello World 2! \n";
return 0;
}
int main() {
std::vector<std::function<int ()>> array;
array.push_back(&hello_world);
array.push_back(std::bind(&hello_world2, 2));
}
Please note, that std::bind and lambdas require you to pass any given parameter at the time of binding. You cannot add the parameter later.
At first it seemed clear that I shouldn't be able to do this, but then I discovered that it can be done with free functions.
Here is an example where I pass void() functions from Child to Parent. The parent calls the function when their Frame comes up.
I have figured out the syntax to pass free functions with arguments, but I can't figure out how to pass a member function of Child with an argument.
Please help.
#include <iostream>
#include <vector>
#include <map>
#include <functional>
void f_Free1() { std::cout << "Hi there hello. I'm a free function without arguments."; }
void f_Free2(int i) { std::cout << "Hi there hello. I'm a free function with an argument. It's " << i; }
class Parent
{
std::map<unsigned int, std::vector<std::function<void()>>> Tasks;
protected:
void addTask(unsigned int frame, std::function<void()> task) { Tasks[frame].push_back(task); }
public:
virtual ~Parent() {}
unsigned int Frame = 0;
void tick()
{
if (Tasks.count(Frame))
{
for (auto task : Tasks[Frame])
{
task();
}
}
Frame++;
}
};
class Child : public Parent
{
void f_Child1() { std::cout << "This is a private Child function without arguments. "; }
void f_Child2(int i) { std::cout << "This is a private Child function with an argument. It's " << i; }
public:
Child()
{
addTask(3, f_Free1);
addTask(5, [a = int(4)] () { f_Free2(a); } ); // THIS WORKS!!!
addTask(7, std::function<void()> { std::bind(&Child::f_Child1, this) });
addTask(9, std::function<void()> { std::bind([a = int(4)]() { &Child::f_Child2(a), this) } }); // CAN'T MAKE THIS WORK
}
};
int main()
{
Child child;
for (unsigned int i = 0; i < 12; i++)
{
std::cout << "[" << child.Frame << "]";
child.tick(); // runs tasks whose frames are up
std::cout << std::endl;
}
return 0;
}
Ditch the bind.
Use [this]() { f_Child1(); } and [this]() { f_Child(4); }.
Also, the free version can be just []() { f_Free2(4); }.
std::bind's syntax would be:
std::bind(&f_Free1)
std::bind(&f_Free2, 4)
std::bind(&Child::f_Child1, this)
std::bind(&Child::f_Child2, this, 4)
But lambda is simpler for most people:
&f_Free1 is fine, else [](){ return f_Free1(); }
[](){ return f_Free2(4); }
[this]() { return this->f_Child1(); )
[this]() { return this->f_Child2(4); )
return can be omitted here as functions return void.
this-> can be omitted in lambda.
you might capture more or differently for arguments.
Is it possible to use a lambda function to create an alias to a template class function? Something like this:
#include <iostream>
using namespace std;
int calcDouble(int a) { return a * 2; }
int calcMultiply_10(int a) { return a * 10; }
struct foo
{
template<void (*func)(int)>
int generic(int value)
{
return func(value);
}
static auto double_10 = [this] { generic<calcDouble>(10); };
static auto double_20 = [this] { generic<calcDouble>(20); };
static auto multiply_10_20 = [this] { generic<calcMultiply_10>(20); };
}
int main() {
foo f;
cout << "double_10: " <<f.double_10() << endl;
cout << "double_20: " <<f.double_20() << endl;
return 0;
}
Your particular example doesn't compile, and would be dangerous if it did - capturing this by value means that as soon as the class is copied/moved the captured this will point to a wrong or invalid memory location.
Just use member functions:
auto double_10() { return generic<calcDouble>(10); }
auto double_20() { return generic<calcDouble>(20); }
auto multiply_10_20() { return generic<calcMultiply_10>(20); }
live example on wandbox
I've just found something as get the name of current function or get name of the caller, some variants to get or call the name as string.
What I want is to get the name of the function that I passed in arguments. Like this:
void Bar()
{
//do something
}
void Foo(void (*f)())
{
//this will output: Foo
std::cout << __FUNCTION__ << std::endl;
//How do I get the name passed to f? (in this case: Bar)
}
int main()
{
Foo(Bar);
return 0;
}
Thanks.
Edit: Here is an extremely near code for what I'm trying following the suggestion of #Jose.
thread_local const char * m_last_function_called = "";
#define register_function() {m_last_function_called = __FUNCTION__;}
inline const char * get_last_function() { return m_last_function_called; }
// const char * g_last_function_called = "";
// #define register_function() { g_last_function_called = __FUNCTION__; }
// inline const char * get_last_function() { return g_last_function_called; }
void print_last_func()
{
static std::mutex sync_cout;
std::lock_guard<std::mutex> l(sync_cout);
std::cout << get_last_function() << std::endl;
}
bool interruptFooTimer = false;
int FooTimer()
{
register_function();
print_last_func();
std::cout << "FooTimer.start" << std::endl;
int t = 0;
while(t<10)
{
if(interruptFooTimer==false)
{
sleep(1);
t++;
std::cout << "\tt=" << t << std::endl;
}
else
{
return -1;
}
}
std::cout << "FooTimer.end" << std::endl;
return 0;
}
void CallTrd(int (*f)())
{
std::thread TrdTemp(f);
TrdTemp.detach();
TrdTemp.~thread();
print_last_func();
}
int main()
{
CallTrd(FooTimer);
print_last_func();
int c = 0;
while(c<15)
{
if(c==7) {interruptFooTimer=true;}
sleep(1);
c++;
std::cout << "c=" << c << std::endl;
print_last_func();
}
return 0;
}
Observe that I call print_last_func() in different moments and all get the same value that was initialized in the variable. This sample code calls a thread without using join() because I can't wait for the thread to finish and also implement the detach() and ~thread to finish my program without any exception. The interruptFooTimer I'm using to safely "terminate" my thread.
What am I missing to get global the value acquired in register_function??
You cannot. __FUNCTION__ is expanded by compiler during the compilation time. You cannot get this information in runtime.
Use a helper macro:
#define Foo(x) FooHelper(#x, x)
void FooHelper(const char *f_name, void (*f)())
{
cout << f_name;
}
As others have already noted, you cannot do this directly.
First of all I would use std::function instead of a raw function pointer and std::string to hold the function's name.
I would also wrap these up like this:
template<class T>
struct Functor
{
std::function<T> functor_;
std::string name_;
Functor(const std::function<T>& functor, const std::string& name)
: functor_(functor)
, name_(name)
{}
};
You can then use it like so:
void Bar()
{
// do something
}
void Foo(const Functor<void()>& functor)
{
}
int main()
{
Functor<void()> f(std::bind(Bar), "Bar");
Foo(f);
return 0;
}
You can also use a macro to make things easier for you.
#define FUNCTOR(t, x, ...) Functor<t>(std::bind(&x, __VA_ARGS__), #x)
Which can be used like this:
int main()
{
auto f = FUNCTOR(void(), Bar);
return 0;
}
Note that if you take this approach that the function name might not be the same as what using __FUNCTION__ yields.
I don't know why you wanna do it, but I hope it's for debugging purpose. Obviously the easiest path is to pass the __FUNCTION__ as an argument as pointed out. But in my point of view, there's a better approach.
You could have for example, a global variable:
thread_local const char * g_last_function_called = "";
#define register_function() { g_last_function_called = __FUNCTION__; }
inline const char * get_last_function() { return g_last_function_called; }
void Bar()
{
register_function()
}
void Foo(void (*f)())
{
std::cout << get_last_function() << std::endl;
}
void my_func_that_doesnt_accept_nulls(CClass * p)
{
if (p == nullptr)
{
std::cout << " function" << get_last_function();
std::cout << "passed a bad pointer, fix it" << std::endl;
return;
}
}
Of course, this will not give you the right result in multi-thread, but you can probably fix that using a thread_local const char * g_last_function_called = "" variable.
The reason why I like this method is because all you have to do to remove it from your project is just a simple "find and replace" of register_function(), and since it uses plain pointers, there's no way it can slow your program at all.
Edit: this is how I'm testing the code
void print_last_func()
{
static std::mutex sync_cout;
std::lock_guard<std::mutex> l(sync_cout);
std::cout << get_last_function() << std::endl;
}
void HelloWorld1()
{
register_function();
print_last_func();
}
void HelloWorld2()
{
register_function();
print_last_func();
}
int main()
{
register_function();
std::thread t1(HelloWorld1);
std::thread t2(HelloWorld2);
print_last_func();
t1.join();
t2.join();
return 0;
}
I get: HelloWorld1, HelloWorld2, and main
I have a macro that implements a retry mechanism that looks like that:
#define RETRY(function_name, param_list, max_attempts, retry_interval_usecs, error_var) \
do { \
int _attempt_; \
\
for (_attempt_ = 0; _attempt_ < max_attempts; _attempt_++) \
{ \
error_var = function_name param_list; \
if (error_var == SUCCESS) \
{ \
break; \
} \
\
usleep(retry_interval_usecs); \
} \
} while (0)
This is functional, but I keep hearing that within a C++ application, defines are not favorable.
Now I looked into a retry function that takes a function pointer as an argument. But I seem to have missed something since I can't get this code to compile.
Note: This code below is NON-Functional, I thought I can post a simple code to illustrate what I want to do:
void retry(int (*pt2Func)(void* args))
{
const int numOfRetries = 3;
int i = 1;
do
{
//Invoke the function that was passed as argument
if((*pt2Func)(args)) //COMPILER: 'args' was not declared in this scope
{
//Invocation is successful
cout << "\t try number#" << i <<" Successful \n";
break;
}
//Invocation is Not successful
cout << "\t try number#" << i <<" Not Successful \n";
++i;
if (i == 4)
{
cout<< "\t failed invocation!";
}
}while (i <= numOfRetries);
}
int Permit(int i)
{
//Permit succeeds the second retry
static int x = 0;
x++;
if (x == 2 && i ==1 ) return 1;
else return 0;
}
int main()
{
int i = 1;
int * args = &i;
retry(&Permit(args));
}
So Basically my question is:
How can I pass a general function with different parameter (in type and number) to the retry method? without encapsulating the functions within a class?
Is that doable?
All existing answers are C++11, so here's a minor modification to your code to make it work using boost (which is C++03)
//takes any function or function like object
//expected function takes no parameters and returns a bool
template<class function_type>
void retry(function_type function, int numOfRetries = 3)
{
int i = 1;
do
{
//Invoke the function that was passed as argument
if(function())
blah blah blah
and in main
int main()
{
int i = 1;
//bind takes a function and some parameters
//and returns a function-like object with a different parameter set
//in this case, the function Permit, and the first thing it gets passed is i
//this means the resulting function-like object doesn't need any parameters
//return type is the same as the original function
retry(boost::bind(Permit, i));
}
Proof of C++03 compilation and execution
The following solution uses C++11 features - the addition that it is not possible to use C++11 was done after the development of the solution started.
One C++ way is using std::function.
The following code gives examples for function, 'callable' classes and lambda expressions.
#include <string>
#include <iostream>
#include <functional>
#include <unistd.h>
// Minimalistic retry
bool retry( std::function<bool()> func, size_t max_attempts,
unsigned long retry_interval_usecs ) {
for( size_t attempt { 0 }; attempt < max_attempts; ++attempt ) {
if( func() ) { return true; }
usleep( retry_interval_usecs );
}
return false;
}
// Ex1: function
int f(std::string const u) {
std::cout << "f()" << std::endl;
return false;
}
// Ex2: 'callable' class
struct A {
bool operator() (std::string const & u, int z) {
++m_cnt;
std::cout << "A::op() " << u << ", " << z << std::endl;
if( m_cnt > 3 ) {
return true;
}
return false;
}
int m_cnt { 0 };
};
int main() {
A a;
bool const r1 = retry( std::bind(f, "stringparam1"), 3, 100 );
bool const r2 = retry( std::bind(a, "stringparam2", 77), 5, 300 );
// Ex 3: lambda
bool const r3 = retry( []() -> bool
{ std::cout << "lambda()" << std::endl; return false; }, 5, 1000 );
std::cout << "Results: " << r1 << ", " << r2 << ", " << r3 << std::endl;
return 0;
}
Tested this with gcc 4.7.2. Output:
f()
f()
f()
A::op() stringparam2, 77
A::op() stringparam2, 77
A::op() stringparam2, 77
A::op() stringparam2, 77
lambda()
lambda()
lambda()
lambda()
lambda()
Results: 0, 1, 0
There are two ways.
Using a variadic template function:
// All in header file:
template <typename F, typename... Args>
void retry1(F func, Args&& ... args) {
//...
if (func(std::forward<Args>(args)...))
; //...
}
// Call like:
retry1(Permit, i);
Or using a std::function and a lambda:
// In header file
void retry2(std::function<bool()> func);
// In a source file
void retry2(std::function<bool()> func) {
//...
if (func())
; //...
}
// Call like:
retry2([]() -> bool { return Permit(i); });
FWIW, i'm trying to fix your initial exmaple. (There may be other drawbacks, and no one will go this way, since there are better solutions)
Your initial definition for retry can be written as:
void retry(int (*pt2Func)(void* args), void* args)
It gets a function pointer (to a function returning and int and a void* argument) and an additional (void*) argument.
The Permit function is now:
int Permit(void* pvi)
The main function now calls the retry/Permit as follows:
retry(&Permit, static_cast<void*>(args));
Complete example
#include <iostream>
using std::cout;
void retry(int (*pt2Func)(void* args), void* args)
{
const int numOfRetries = 3;
int i = 1;
do
{
//Invoke the function that was passed as argument
if((*pt2Func)(args)) //not changed: args is now declared
{
//Invocation is successful
cout << "\t try number#" << i <<" Successful \n";
break;
}
//Invocation is Not successful
cout << "\t try number#" << i <<" Not Successful \n";
++i;
if (i == 4)
{
cout<< "\t failed invocation!";
}
}while (i <= numOfRetries);
}
int Permit(void* pvi)
{
//Permit succeeds the second retry
int i = *(static_cast<int*>(pvi));
static int x = 0;
x++;
if (x == 2 && i ==1 ) return 1;
else return 0;
}
int main()
{
int i = 1;
int * args = &i;
retry(&Permit, static_cast<void*>(args));
}
Well, if you're using C++11, you have Lambda Expressions.
There's also this question: Write a function that accepts a lambda expression as argument that provides another relevant example.
EDIT after seeing you can't use C++11
In that case, I'd just keep the macro and forget about it. While some people might frown upon it, you have a good reason to use it - it's easier and makes more sense than another solution. Just write that in a comment above the macro, so that 5 years from now when people try to figure out why you decided not to use std:forward or lambda expressions, they'll know.