Search code examples
c++functionc++11variadic-templatesstdbind

cannot bind variadic function and save to a std::function


I successfully implemented my own thread_pool class where I can submit lambdas that can return any value but can only take zero arguments. I would like to improve it, such that it can work like std::async, where one can call it as follows: std::async(my_function, arg_1, arg_2, ..., arg_n). As I have it right now it looks as follows:

template<typename T>
auto enqueue_task(T&& task) -> std::future<decltype(task())>
{
    auto wrapper = std::make_shared<std::packaged_task<decltype(task())()>>(std::forward<T>(task));
    {
        //some mutex
        std::unique_lock<std::mutex> mutex(mutex_);
        //The task is added to a queue of std::function<void()>
        tasks_.emplace([=] {(*wrapper)(); });
    }
    has_work_.notify_one();
    return wrapper->get_future();
}

My ideal solution would be such, that I can pass arguments to functinons in my thread_pool like such:

pool.enqueue_task(my_function, arg_1, arg_2, ..., arg_n)

where arg_1, ..., arg_n are the arguments of my_func

For this I sucessfully create a function which can take a variadic amount of arguments, but I have not managed to save this function int my std::function queue. I read on this link: Passing a variadic function as argument how to achieve my goal by using std::bind. Yet I have not managed to achieve my goal. Here is how I understood it, what turned out not to work:

//some function with variadic arguments
template <typename... Args>
void test1(Args&&... args)
{

}

void test2(int a)
{
}

//main method
std::function<void()> a = std::bind(test2, 2) //works
std::function<void()> b = std::bind(test1<int>, 1) //does not work

Solution

  • std::bind will pass argument as lvalue. From cppreference:

    the ordinary stored argument arg is passed to the invokable object as lvalue argument

    When you specify test1<int>, the function becomes void test1(int&&), which cannot accept lvalue.