Reputation: 1103
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
Upvotes: 0
Views: 62
Reputation: 180630
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();
});
Upvotes: 1
Reputation: 962
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.
Upvotes: 2
Reputation: 3277
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;
}
Upvotes: 1
Reputation: 6395
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).
Upvotes: 1