template <typename C, typename F, typename... Args>
void MyClass::run(F C::*f, C* c, Args&&... args) {
td_ = std::make_unique<std::thread>(
[](F C::*f, C* c, Args... args){ // Is this correct?
c.f(args...); // should I code c.f(std::forward<Args>(args)...); here?
});
}
I know what std::forward
is used for. But in the case above, the types of parameters are passed to a lambda, which is in the template function. I'm kind of confused now...
// The perfect forwarding is a bit of a thing, and you need std::apply
// Also when writing a library like this you should give client code a chance
// to syncrhonize with the threads you spawn
// AND you have to think about exception handling on the threads you spawn
// never trust your clients not to add a function that will not throw.
// In this example I rely on std::async/std::future to do that for now.
#include <future>
#include <type_traits>
#include <iostream>
//-----------------------------------------------------------------------------
template<typename fn_t>
auto run(fn_t fn)
{
return std::async(std::launch::async, fn);
}
template <typename class_t, typename fn_t, typename... args_t>
auto run(class_t& c, fn_t class_t::*fn, args_t&&... args)
{
// make a local lambda first so we can reuse impl of run
// perfect forwarding of args
// mutable is necessary to be able to call non-const methods on class_t
auto lambda = [fn=fn, args = std::make_tuple(c, std::forward<args_t>(args) ...)]() mutable
{
return std::apply(fn, args);
};
return run(lambda);
}
//-----------------------------------------------------------------------------
struct test_t
{
void fn(int value)
{
std::cout << "test_t::fn(" << value << ")\n";
};
void fn_noexcept(int value) noexcept
{
std::cout << "test_t::fn_noexcept(" << value << ")\n";
};
};
//-----------------------------------------------------------------------------
int main()
{
test_t test;
auto future1 = run([&] { test.fn(1); });
future1.get(); // give output a chance to appear
auto future2 = run(test, &test_t::fn,2);
future2.get(); // give output a chance to appear
return 0;
}