не может связать вариативную функцию и сохранить в std::function

Я успешно реализовал свой собственный класс thread_pool, в котором я могу отправлять лямбда-выражения, которые могут возвращать любое значение, но могут принимать только нулевые аргументы. Я хотел бы улучшить его, чтобы он мог работать как std::async, где его можно вызвать следующим образом: std::async(my_function, arg_1, arg_2, ..., arg_n). У меня сейчас это выглядит так:

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();
}

Мое идеальное решение было бы таким, чтобы я мог передавать аргументы функциям в моем thread_pool следующим образом:

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

где arg_1, ..., arg_n аргументы my_func

Для этого я успешно создал функцию, которая может принимать переменное количество аргументов, но мне не удалось сохранить эту функцию в моей очереди std::function. Я прочитал по этой ссылке: Передача функции с переменным числом аргументов в качестве аргумента, как достичь моего цель с помощью std::bind. И все же мне не удалось достичь своей цели. Вот как я понял, что оказалось не работать:

//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

person Stefan B    schedule 21.05.2018    source источник
comment
есть ли причина использовать bind вместо лямбда? b = [](){ test1(1); }; должно работать.   -  person clcto    schedule 21.05.2018
comment
test1<int> имеет подпись void test1(int&& arg). Принимает только ссылку rvalue.   -  person Justin    schedule 21.05.2018
comment
Вы пытаетесь передать lvalue типа int функции, созданной из test1 как test1(int&&), которая не работает. Возможно, вы захотите изменить test1(Args&&...) на test1(Args...).   -  person Edgar Rokjān    schedule 21.05.2018
comment
Или используйте test1<int&> вместо test<int>.   -  person gflegar    schedule 22.05.2018


Ответы (1)


std::bind будет передавать аргумент как lvalue. Из cppreference:

обычный сохраненный аргумент arg передается вызываемому объекту как аргумент lvalue

Когда вы указываете test1<int>, функция становится void test1(int&&), которая не может принимать lvalue.

person llllllllll    schedule 21.05.2018