The following code compiles on Windows under MSVC 2022 in a C++17 mode, but fails to compile on Linux with both GCC 11.3 and Clang 16.0 compilers.
#include <vector>
#include <future>
#include <numeric>
#include <thread>
using namespace std;
template <class T>
T parallel_accumulate(const std::vector<T>& v)
{
packaged_task pt0{accumulate<const T*, T>};
packaged_task pt1{accumulate<const T*, T>};
future f0{pt0.get_future()};
future f1{pt1.get_future()};
thread t0{move(pt0), &v[0], &v[v.size() / 2], 0};
thread t1{move(pt1), &v[v.size() / 2], &v[0] + v.size(), 0};
t0.join();
t1.join();
return f0.get() + f1.get();
}
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include <doctest/doctest.h>
TEST_CASE("accumulate")
{
constexpr size_t checks_count = 10;
std::vector<int> v;
v.reserve(checks_count);
for (size_t i = 1; i <= checks_count; ++i)
{
v.push_back(i);
CHECK(parallel_accumulate(v) == i * (i + 1) / 2);
}
}
The error under GCC is:
/home/bobeff/projects/cpp/cpp_programming_language/05_a_tour_of_cpp_concurrency_and_utilities/packaged_task.cpp:39:5: required from here
/home/bobeff/projects/cpp/cpp_programming_language/05_a_tour_of_cpp_concurrency_and_utilities/packaged_task.cpp:11:17: error: class template argument deduction failed:
11 | packaged_task pt0{accumulate<const T*, T>};
| ^~~
/home/bobeff/projects/cpp/cpp_programming_language/05_a_tour_of_cpp_concurrency_and_utilities/packaged_task.cpp:11:17: error: no matching function for call to ‘packaged_task(<unresolved overloaded function type>)’
In file included from /home/bobeff/projects/cpp/cpp_programming_language/05_a_tour_of_cpp_concurrency_and_utilities/packaged_task.cpp:2:
/usr/include/c++/11/future:130:11: note: candidate: ‘template<class _Signature> packaged_task()-> std::packaged_task<_Signature>’
130 | class packaged_task;
| ^~~~~~~~~~~~~
/usr/include/c++/11/future:130:11: note: template argument deduction/substitution failed:
/home/bobeff/projects/cpp/cpp_programming_language/05_a_tour_of_cpp_concurrency_and_utilities/packaged_task.cpp:11:17: note: candidate expects 0 arguments, 1 provided
11 | packaged_task pt0{accumulate<const T*, T>};
| ^~~
In file included from /home/bobeff/projects/cpp/cpp_programming_language/05_a_tour_of_cpp_concurrency_and_utilities/packaged_task.cpp:2:
/usr/include/c++/11/future:130:11: note: candidate: ‘template<class _Signature> packaged_task(std::packaged_task<_Signature>)-> std::packaged_task<_Signature>’
130 | class packaged_task;
| ^~~~~~~~~~~~~
/usr/include/c++/11/future:130:11: note: template argument deduction/substitution failed:
/home/bobeff/projects/cpp/cpp_programming_language/05_a_tour_of_cpp_concurrency_and_utilities/packaged_task.cpp:11:17: note: mismatched types ‘std::packaged_task<_Signature>’ and ‘int (*)(const int*, const int*, int)’
11 | packaged_task pt0{accumulate<const T*, T>};
| ^~~
/home/bobeff/projects/cpp/cpp_programming_language/05_a_tour_of_cpp_concurrency_and_utilities/packaged_task.cpp:11:17: note: couldn’t deduce template parameter ‘_Signature’
and under Clang it is:
/home/bobeff/projects/cpp/cpp_programming_language/05_a_tour_of_cpp_concurrency_and_utilities/packaged_task.cpp:11:17: error: no viable constructor or deduction guide for deduction of template arguments of 'packaged_task'
packaged_task pt0{accumulate<const T*, T>};
^
/home/bobeff/projects/cpp/cpp_programming_language/05_a_tour_of_cpp_concurrency_and_utilities/packaged_task.cpp:39:11: note: in instantiation of function template specialization 'parallel_accumulate<int>' requested here
CHECK(parallel_accumulate(v) == i * (i + 1) / 2);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/future:130:11: note: candidate template ignored: could not match 'packaged_task<_Signature>' against 'int (*)(const int *, const int *, int)'
class packaged_task;
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/future:130:11: note: candidate function template not viable: requires 0 arguments, but 1 was provided
Why does class template arguments deduction fail under GCC/Clang and how to fix the code to work on all compilers?
The deduction guides for packaged_task
were added after LWG3117, so you need a compiler such as gcc-12 that already implements it.