将函数对象及其参数传递给std :: thread构造函数时的编译错误

时间:2016-11-25 17:08:21

标签: c++ c++11 compiler-errors

我正在尝试编译以下代码,但是在threads[i] = std::thread(find_elements[i], block_start, block_end, match);行上,std::thread对象无法使用给定的参数构造。

#include <iostream>
#include <thread>
#include <vector>
#include <future>

class join_threads
{
public:
  explicit join_threads(std::vector<std::thread>& threads)
    : threads_(threads) {}

  ~join_threads()
  {
    for (size_t i = 0; i < threads_.size(); ++i)
    {
      if(threads_[i].joinable())
      {
        threads_[i].join();
      }
    }
  }

private:
  std::vector<std::thread>& threads_;
};

template <typename Iterator, typename MatchType>
Iterator parallel_find(Iterator first, Iterator last, MatchType match)
{
  class find_element
  {
  public:
    void operator()(Iterator begin, Iterator end, MatchType match)
    {
      try
      {
        while (begin != end)
        {
          if (*begin == match)
          {
            result_.set_value(begin);
            is_found_ = true;
            return;
          }
          ++begin;
        }
        result_.set_value(end);
      }
      catch(...)
      {
        result_.set_exception(std::current_exception());
      }
    }

    Iterator get() { return result_.get_future().get(); }
    bool is_found() const { return is_found_; }

  private:
    std::promise<Iterator> result_;
    bool is_found_ = false;
  };

  const unsigned length = std::distance(first, last);

  if (0 == length) return last;

  const unsigned min_per_thread = 25;
  const unsigned max_threads = (length + min_per_thread - 1) / min_per_thread;
  const unsigned hardware_threads = std::thread::hardware_concurrency();
  const unsigned num_threads = std::min(
        hardware_threads != 0 ? hardware_threads : 2, max_threads);
  const unsigned block_size = length / num_threads;

  std::vector<std::thread> threads(num_threads - 1);
  std::vector<find_element> find_elements(num_threads);

  {
    join_threads joiner(threads);
    Iterator block_start = first;
    for (unsigned i = 0; i < num_threads - 1; ++i)
    {
      Iterator block_end = block_start;
      std::advance(block_end, block_size);
      threads[i] = std::thread(find_elements[i], block_start, block_end, match);
      block_start = block_end;
    }

    find_elements[num_threads - 1](block_start, last, match);
  }

  for (unsigned i = 0; i < num_threads - 1; ++i)
  {
    if (find_elements[i].is_found())
    {
      return find_elements[i].get();
    }
  }

  return find_elements[num_threads - 1].get();
}

int main()
{
  std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8 };
  parallel_find(v.begin(), v.end(), 9);

  return 0;
}

clang ++ 版本 3.9.1 产生的确切错误如下:

In file included from ../../../sources/test/main.cpp:2:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/thread:39:
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/functional:1379:11: error: no matching constructor for initialization of 'std::tuple<find_element, __normal_iterator<int *, vector<int, allocator<int> > >, __normal_iterator<int *, vector<int, allocator<int> > >, int>'
        : _M_bound(std::forward<_Tp>(__f), std::forward<_Up>(__args)...)
          ^        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/functional:1426:14: note: in instantiation of function template specialization 'std::_Bind_simple<find_element (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >, int)>::_Bind_simple<const find_element &, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, int &>' requested here
      return __result_type(
             ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/thread:137:13: note: in instantiation of function template specialization 'std::__bind_simple<find_element &, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, int &>' requested here
              std::__bind_simple(std::forward<_Callable>(__f),
                   ^
../../../sources/test/main.cpp:84:20: note: in instantiation of function template specialization 'std::thread::thread<find_element &, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, int &>' requested here
      threads[i] = std::thread(find_elements[i], block_start, block_end, match);
                   ^
../../../sources/test/main.cpp:105:3: note: in instantiation of function template specialization 'parallel_find<__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >, int>' requested here
  parallel_find(v.begin(), v.end(), 9);
  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:600:18: note: candidate template ignored: disabled by 'enable_if' [with _Dummy = void]
                 _TCC<_Dummy>::template
                 ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:611:18: note: candidate template ignored: disabled by 'enable_if' [with _Dummy = void]
                 _TCC<_Dummy>::template
                 ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:628:5: note: candidate template ignored: disabled by 'enable_if' [with _UElements = <const find_element &, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, int &>]
                  _TC<sizeof...(_UElements) == 1, _Elements...>::template
                  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:641:5: note: candidate template ignored: disabled by 'enable_if' [with _UElements = <const find_element &, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, int &>]
                  _TC<sizeof...(_UElements) == 1, _Elements...>::template
                  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:737:19: note: candidate template ignored: disabled by 'enable_if' [with _Alloc = __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >, _UElements = <__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, int &>]
        enable_if<_TMC<_UElements...>::template
                  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:748:19: note: candidate template ignored: disabled by 'enable_if' [with _Alloc = __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >, _UElements = <__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > &, int &>]
        enable_if<_TMC<_UElements...>::template
                  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:579:17: note: candidate constructor template not viable: requires 0 arguments, but 4 were provided
      constexpr tuple()
                ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:589:26: note: candidate constructor template not viable: requires 0 arguments, but 4 were provided
      explicit constexpr tuple()
                         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:670:19: note: candidate constructor template not viable: requires single argument '__in', but 4 arguments were provided
        constexpr tuple(const tuple<_UElements...>& __in)
                  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:682:28: note: candidate constructor template not viable: requires single argument '__in', but 4 arguments were provided
        explicit constexpr tuple(const tuple<_UElements...>& __in)
                           ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:694:19: note: candidate constructor template not viable: requires single argument '__in', but 4 arguments were provided
        constexpr tuple(tuple<_UElements...>&& __in)
                  ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:705:28: note: candidate constructor template not viable: requires single argument '__in', but 4 arguments were provided
        explicit constexpr tuple(tuple<_UElements...>&& __in)
                           ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:721:2: note: candidate constructor template not viable: requires 6 arguments, but 4 were provided
        tuple(allocator_arg_t __tag, const _Alloc& __a,
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:732:11: note: candidate constructor template not viable: requires 6 arguments, but 4 were provided
        explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
                 ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:711:2: note: candidate constructor template not viable: requires 2 arguments, but 4 were provided
        tuple(allocator_arg_t __tag, const _Alloc& __a)
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:759:2: note: candidate constructor template not viable: requires 3 arguments, but 4 were provided
        tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:763:2: note: candidate constructor template not viable: requires 3 arguments, but 4 were provided
        tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:772:2: note: candidate constructor template not viable: requires 3 arguments, but 4 were provided
        tuple(allocator_arg_t __tag, const _Alloc& __a,
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:784:11: note: candidate constructor template not viable: requires 3 arguments, but 4 were provided
        explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
                 ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:796:2: note: candidate constructor template not viable: requires 3 arguments, but 4 were provided
        tuple(allocator_arg_t __tag, const _Alloc& __a,
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:808:11: note: candidate constructor template not viable: requires 3 arguments, but 4 were provided
        explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
                 ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:654:17: note: candidate constructor not viable: requires 1 argument, but 4 were provided
      constexpr tuple(tuple&&) = default; 
                ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.2.0/../../../../include/c++/6.2.0/tuple:652:17: note: candidate constructor not viable: requires 1 argument, but 4 were provided
      constexpr tuple(const tuple&) = default;
                ^
1 error generated.
make: *** [main.o] Error 1

0 个答案:

没有答案