2015-10-30 6 views
2

У меня есть класс с функцией под названием Епдиеим:Pass член Функции VARIADIC шаблон Функция

template<class T, class... Args> 
inline auto ThreadPool::enqueue(T && t, Args&&... args) ->std::future<typename std::result_of<T(Args ...)>::type> 
{ 
    using return_type = typename std::result_of<T(Args...)>::type; 

    auto task = std::make_shared<std::packaged_task<return_type()>> (
     std::bind(std::forward<T>(t), std::forward<Args>(args)...) 
    ); 

    std::future<return_type> result = task->get_future(); 
    { 
     std::unique_lock<std::mutex> lock(m_mutex); 

     // Don't allow job creation after stopping pool. 
     if (m_done) 
      throw std::runtime_error("Enqueue on stopped ThreadPool."); 

     m_tasks.emplace([task]() { (*task)(); }); 
    } 

    m_cond.notify_one(); 
    m_futures.push_back(move(result)); 
    return result; 
} 

Это реализация рядной выполняется внутри файл заголовка рядом с классом ThreadPool.

Это одноэлементный номер и должен иметь возможность использовать любую функцию с аргументами, добавить это в очередь задач и вернуть будущее типа результата этой функции.

Вот класс, где я пытаюсь использовать:

void Grepper::scan(std::tr2::sys::path const& folder, std::string expression, bool verbose) { 
    // Create directory iterators. 
    std::tr2::sys::recursive_directory_iterator d(folder); 
    std::tr2::sys::recursive_directory_iterator e; 

    // Create tasks from files that match initial extension list. 
    for (; d != e; ++d) { 
     if (!std::tr2::sys::is_directory(d->status()) && std::find(m_extensions.begin(), m_extensions.end(), d->path().extension().generic_string()) != m_extensions.end()) { 
      ThreadPool::get_instance().enqueue(grep, d->path(), expression, verbose); 
     } 
    } 
} 

Что дает ошибку компилятора:

Error C3867 'Grepper::grep': non-standard syntax; use '&' to create a pointer to member 

Я попытался создать функтор к этой функции, а также прохождения функция как лямбда:

ThreadPool::get_instance().enqueue([this](std::tr2::sys::path p, std::string s, bool b) { grep(p, s, b); }); 

Что дает мне следующую ошибку компилятора:

Error C2893 Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)' 

Для справки здесь является декларация моего метода Grep:

void grep(std::tr2::sys::path file, std::string expression, bool verbose); 

Как передать эту функцию и ее аргументы правильно методу Ставить?

+0

Использование 'bind' просто неправильно при вычислении' result_of' напрямую. –

+0

@ T.C.Может быть, это причина, по которой это не позволяет мне передавать функции-члены? – Delete

+0

* «Я попытался создать функтор для этой функции, а также передать функцию как лямбда:« *, вы, вероятно, должны использовать «ThreadPool :: get_instance(). Enqueue ([this] (std :: tr2 :: sys :: path p, std :: string s, bool b) {grep (p, s, b);}, d-> path(), выражение, verbose); 'или' ThreadPool :: get_instance(). enqueue ([это, d, выражение, verbose] {grep (d-> path(), выражение, verbose);}); ' –

ответ

2

Попытка с указателем на функцию-член не может по двум причинам:

  1. Чтобы сформировать указатель на функцию-член, вам нужно использовать &Grepper::grep синтаксис.
  2. Функция-член требует неявного параметра объекта (среди других аргументов, так что он также может быть правильно обработан std::bind и std::result_of).

Сказав это, вы можете попробовать следующий вызов:

ThreadPool::get_instance().enqueue(
    &Grepper::grep 
    , this 
    , d->path() 
    , expression 
    , verbose 
); 

Попытка с лямбда-выражения терпит неудачу, потому что лямбда-выражение передается в качестве аргумента:

[this] (std::tr2::sys::path p, std::string s, bool b) { grep(p, s, b); } 

декларирует три параметров, поэтому пакет параметров Args не должен быть пустым. Но это в вашем случае:

ThreadPool::get_instance().enqueue(
    [this] (std::tr2::sys::path p, std::string s, bool b) { grep(p, s, b); }   
); 

Эти аргументы, согласно вашей конструкции, должен быть либо принят в вызове enqueue:

ThreadPool::get_instance().enqueue(
    [this] (std::tr2::sys::path p, std::string s, bool b) { grep(p, s, b); } 
    , d->path() 
    , expression 
    , verbose 
); 

или захваченной лямбда-выражения, так что не требуется дополнительных Args:

ThreadPool::get_instance().enqueue(
    [this,d,expression,verbose] { grep(d->path(), expression, verbose); } 
); 
Смежные вопросы