我正在尝试编译以下代码,但是在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