My title is my main question.
The code below shows what i want to do, but it causes an error.
class B
{
public:
void DoSomething(void (*func)())
{
func();
}
};
class A
{
public:
int x;
void Start(B* b)
{
auto func = [this]()->void
{
this->x++;
};
b->DoSomething(func);
}
};
If I remove the "this" keyword, then the program works, but then I cant reference the x variable.
So how can I achieve this?
Change
void DoSomething( void (*func)() )
to
void DoSomething( std::function<void()> func )
Your current parameter type void (*func)() is a function pointer, which is a type of callable (something that can be called like a function) that doesn't hold state. That is why your variable this can't be passed into the function.
Only lambdas that capture nothing can be converted to a stateless function pointer.
std::function however can represent (almost) anything callable. It could be a raw function, or an instance of a class that implements operator(), or it could be your lambda holding state.
An alternative is to simply use templates to avoid the potential overhead associated with large lambdas that need to be packaged by std::function.
#include <functional>
using namespace std;
template<typename Callable>
void DoSomething(Callable c) { c(); } // calls the lambda with no args
int main()
{
DoSomething([]{ printf("Hello\n"); });
DoSomething([msg = "World"] { printf("%s\n", msg); });
}
Live Code: http://goo.gl/LMvm3a
Related
What is the correct way of passing a member function to thread
class foo{
public:
int sum(int a ,int b)
{
std::cout<<a+b;
}
};
i need to pass this function to a thread in my main function.I have seen an example
#include <thread>
#include <iostream>
class SayHello
{
public:
void greeting(std::string const& message) const
{
std::cout<<message<<std::endl;
}
};
int main()
{
SayHello x;
std::thread t(&SayHello::greeting,&x,"goodbye");
t.join();
}
why do we need to pass the reference to the object in this case?
why do we need to pass the reference to the object in this case?
A member function, apart from the "normal" arguments, also takes a pointer to the object (this). This one is implicitly provided when you call with the normal syntax:
x.apply_greeting("goodbye"); //secretly calls apply_greeting(&x,"goodbye"). (not valid code!)
So when you have a pointer to a member function which you have when you write &SayHello::greeting, you need to provide the pointer to the object as well. Otherwise - how would it know about its member variables?
Pointer to member functions are messy, you can circumvent by using a lambda:
std::thread t([&x](){ x.greeting("goodbye!"); } );
I know it's not a perfect answer to the question. But in my experience of C++03, manage member functions is a hard work, especally when the code is shared with beginners in C++. My habit is the following:
class SayHello
{
public:
void greeting(std::string const& message) const
{
std::cout << message << std::endl;
}
};
void apply_greeting(SayHello const* say_hello, std::string const* message)
{
say_hello->greeting(*message);
}
int main()
{
SayHello x;
const std::string message = "goodbye";
std::thread t(apply_greeting, &x, &message); // I'm not sure for this line, my habit is C++03 with boost::thread and boost::bind
t.join();
return 0;
}
I'm creating an onClick function. The premise is that when a button is clicked, It will call a function like so:
// This connects the callback to the button class method named "something"
something.onClick(&callback, "a string", 123);
// This is called when the button is clicked
callback("a string", 123);
I'm already using a function pointer to call the function callback, however I don't know how to accept a variable number of arguments. The API I want is exactly like I specified above: the first parameter is the function, and each subsequent parameter is an argument to be passed. So far I've thought about using boost::bind, but am unable to figure out how that will fit in with what I'm attempting.
You can just capture the supplied arguments in a lambda. This can't be stored in a function pointer, so use std::function
class Something
{
public:
template <typename Func, typename ... Args
void onClick(Func&& func, Args&& ... args)
{
m_onClick = [=]{ func(args...); };
}
private:
std::function<void()> m_onClick;
// call m_onClick somewhere
};
int main () {
Something something;
something.onClick(&callback, "a string", 123);
}
How would you call the function if you dont know how many parameters it has? There are solutions for that, but why not keep it simple...
Lets say you want to use either one of the two as callback:
void foo(std::string x) {}
void bar(int x) {}
Then you can wrap them together with the parameters in a lambda and store it in a std::function like that:
#include <string>
#include <functional>
void foo(std::string x) {}
void bar(int x) {}
struct caller {
std::function<void()> callback;
void call() { callback(); }
};
int main(){
caller c{ [](){ foo("test"); }};
c.call();
caller d{ [](){ bar(1); }};
d.call();
}
If the parameters to be passed are supposed to be more dynamic you need something more of course.
In the following code, I have a variable called data. It holds a functions inside itself to call them later. Let's assume data is defined in another library and I cannot change its type. I assign a template function to each member of it where a portion of this function is known (s3) and a portion must be given when it is called (true). I cannot pass something like this:
data[0]=test_func(?,s3); // error
instead, I have to pass a lambda function to it :
data[0]=[](bool b){test_func(b,s3);}; // ok
But the lambda function does not look neat especially when we have an array of 100 of these assignments. It there any way to avoid lambda functions by just changing the test_func in any way? even using lambda inside test_func is ok to me because it is just written once.
#include <iostream>
#include <functional>
template<typename F>
void test_func(bool b,F f)
{
if(b)
f();
}
void s1()
{
std::cout<<"s1 \n";
}
void s2()
{
std::cout<<"s2 \n";
}
void s3()
{
std::cout<<"s3 \n";
}
int main()
{
test_func(true,s1);
test_func(true,s2);
test_func(false,s1);
test_func(true,s2);
/////////////////
std::function<void(bool)> data[100];
// data=test_func(?,s3); // error
data[0]=[](bool b){test_func(b,s3);}; // ok
data[0](true);
return 0;
}
If you want to avoid a lambda function completely as well as templates you can use a functional (class with operator()):
typedef void (&F)(void);
class TestFunc {
F f;
public:
TestFunc(const F f) : f(f) {}
void operator()(bool B) const {
if(B) f();
}
};
Assign it with TestFunc(s3). Just typedef F to the function type, no need for a template:
typedef void (&F)(void);
and remove the template completely - I usually prefer less templates if possible, but that's taste. A template would only really be called for if you need different function signature support.
To use a standard library functional just change the typedef:
typedef std::function<void(void)> F;
If each s_n is a regular function with an identical signature, you can just remove that f parameter from test_func and instead pass the function itself as template parameter.
template<void(&f)()>
void test_func(bool b)
{
if(b)
f();
}
And use like this:
data[0] = test_func<s1>;
Function pointers and references are explicitly allowed as template non-type parameters by [temp.param/4]:
A non-type template-parameter shall have one of the following
(optionally cv-qualified) types:
[...]
pointer to object or pointer to function,
lvalue reference to object or lvalue reference to function,
You could create your lambda in a helper function:
#include <iostream>
#include <string>
#include <functional>
#include <vector>
template<typename F>
void test_func(bool b,F f) {
if(b) {
f();
}
}
std::function<void(bool)> wrap_function(const std::function<void(void)> &f) {
return [f](bool b){test_func(b,f);};
}
void s1() {
std::cout<<"s1 \n";
}
int main() {
std::vector<std::function<void(bool)>> data;
data.push_back(wrap_function(s1));
data[0](true);
}
And you should use std::vector, std::array or another std container instead of std::function<void(bool)> data[100]
The following is a timer.
template <typename Duration, typename Function>
void timer(Duration const & d, Function const & f)
{
std::thread([d,f](){
std::this_thread::sleep_for(d);
f();//error here
}).detach();
}
Sample myclass definition is
class myclass {
public:
void my_functions() const {
std::cout << "my_functions called";
}
};
And I call it like this:
timer(std::chrono::milliseconds(10), &myclass::my_functions());
When I try to call it on a member function I get error C2064: term does not evaluate to a function taking 0 arguments
To pass a non-static member function to another function you need to utilize std::function and std::bind from functional header, as well as instantiate the object
myclass mc;
timer(std::chrono::milliseconds(1), std::bind(&myclass::my_functions, mc));
However, your code might not work as expected, because to see the message you must wait for the thread to make a call. Here's a simple example of a working one
#include <thread>
#include <iostream>
#include <functional>
#include <chrono>
template <typename Duration, typename Function>
void timer(Duration const & d, Function const & f)
{
std::thread([d, f](){
std::this_thread::sleep_for(d);
f();//error here
}).detach();
}
class myclass{
public:
void my_functions() const {
std::cout << "aaa";
}
};
int main(){
myclass mc;
timer(std::chrono::milliseconds(1), std::bind(&myclass::my_functions, mc));
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
}
The proper way would be of course to wait for thread completion.
Also, if the sole purpose of your member function is to output a message, you can make it static and do without binding.
You cannot call non-static methods/functions without an object instance (even if the object is not really needed inside the method/function).
To achieve a method call without the need for an object, declare that method static (can still be inside the class, but add static before its name).
If you are okay to charge argument list of your timer() function then this will also works.
#include <iostream>
#include <chrono>
#include <thread>
template <typename Duration, typename Function, typename Class>
void timer(Duration const & d, Function const & f,Class const& o)
{
std::thread([d,f,o](){
std::this_thread::sleep_for(d);
f(o);//error here
}).detach();
}
class Foo{
public:
Foo() {}
void func() const {
std::cout<<__func__<<":"<<__LINE__<<std::endl;};
}
int main(){
std::function<void(const Foo&)> foo_func = &Foo::func;
const Foo foo;
timer(std::chrono::seconds(2),foo_func,foo);
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}
The issue here is a non static member function is not the same as a regular or static function. It has a hidden parameter that it takes and that is pointer to the object the function is being called on.
You have a couple ways to fix this. First you can make it static and then it treats it just like a normal function whose name is scopeed to the class. If you cannot do that then you can use std::bind to create function like object that you can call the function operator on. It would be used like
timer(std::chrono::milliseconds(10), std::bind(&class_name::my_functions(), &class_instance));
Lastly you could use a lambda to wrap the call just like bind does. For that the syntax would be
timer(std::chrono::milliseconds(10), [&class_instance](){
return class_instance.my_functions();
});
I have the following function:
void PerformAction(void(*pf_action)());
and the following class:
class A
{
public:
void DoSomething();
}
I want to be able to do this:
int main()
{
A a;
PerformAction(&(a.DoSomething);
return 0;
}
I have seen many answers that say that the function signature should be:
void PerformAction(void(A::*)());
This is not what I want.
I want to able to pass it any function/method that receives no parameters and returns void. Not just member methods of A or just global functions.
Is this possible in C++?
Plain function pointers and member function pointers are different things.
Member functions take a hidden this parameter, whereas plain functions do not. To call a member function through a pointer an object is required to initialize that this parameter.
Hence, you cannot convert a pointer to a non-static member function to a plain function pointer and call through it without passing in an object.
I want to able to pass it any function/method that receives no parameters and returns void. Not just member methods of A or just global functions.
Is this possible in C++?
Yes, it is possible, but you need to use a more flexible type. The way to achieve this is to specify the PerformAction function with a different type. You want to use a type that is callable with zero arguments and returns void, std::function<void ()>. For example change the PerformAction function to be: void PerformAction(std::function<void ()> fn);. This version will allow you to accept anything that's callable with zero arguments and returns void, see the following code for an example.
Example Code
#include <functional>
#include <iostream>
class Foo
{
public:
void bar() { std::cout << "Member function: Foo::bar()\n"; }
};
void bar()
{
std::cout << "Free function: bar()\n";
}
class Functor
{
public:
void operator()() { std::cout << "Functor object\n"; }
};
auto lambda = []() { std::cout << "Lambda expression\n"; };
void doSomething(std::function<void ()> fn)
{
fn();
}
int main()
{
doSomething(bar);
doSomething(Functor());
doSomething(lambda);
Foo foo;
doSomething(std::bind(&Foo::bar, &foo));
return 0;
}
Live Example
Example Output
Free function: bar()
Functor object
Lambda expression
Member function: Foo::bar()