'Nothing is fixing the error "No match for function call" C++

I can't fix this error for the life of me.

I'm trying to measure the time it takes to run a function (which counts prime numbers in a vector, but that's beside the point) sequentially, then in parallel. There are other header files, but I included only the code relevant to the error.

Error:

prog.cpp:32:22: error: no matching function for call to ‘results_benchmark(int,
do_work<const __pstl::execution::v1::sequenced_policy, std::vector<unsigned int>*>::
<lambda(int, int)>)’

More details on the error:

In file included from prog.cpp:8:
benchmark.hpp:95:16: note: candidate: ‘template<class Op, class ... Args> constexpr
benchmark_results<typename std::invoke_result<_Functor, _ArgTypes>::type>
results_benchmark(const size_t&, Op&&, Args&& ...)’
   95 | constexpr auto results_benchmark(
      |                ^~~~~~~~~~~~~~~~~
benchmark.hpp:95:16: note:   template argument deduction/substitution failed:
benchmark.hpp: In substitution of ‘template<class Op, class ... Args> constexpr 
benchmark_results<typename std::invoke_result<_Functor, _ArgTypes>::type> 
results_benchmark(const size_t&, Op&&, Args&& ...) [with Op = do_work<const 
__pstl::execution::v1::sequenced_policy, std::vector<unsigned int>*>::<lambda(int, int)>; 
Args = {}]’:

prog.cpp:32:22:   required from ‘auto do_work(ExecPolicy&, const Container&) [with 
ExecPolicy = const __pstl::execution::v1::sequenced_policy; Container = std::vector<unsigned 
int>*]’
test_a07.cpp:107:46:   required from here
benchmark.hpp:95:16: error: no type named ‘type’ in ‘struct std::invoke_result<do_work<const 
__pstl::execution::v1::sequenced_policy, std::vector<unsigned int>*>::<lambda(int, int)> >’

This is how I defined the function in question. It takes an int (number of times to run the lambda function) and a lambda.

The lambda accepts by reference an execution policy and a vector. It has only one line: a return statement calling count_if(), to which I pass the exec policy, begin(v) and end(v), and the function used to determine whether a number is prime.

template <typename ExecPolicy, typename Container>
auto do_work(ExecPolicy& ep, Container const& v)
{
    auto return_from_results_benchmark = 
    results_benchmark(3, 
        [&](auto ep, auto v){
            return count_if(ep, begin(v), end(v), is_prime_trial_division);
        }
    );

    // some print statements... 

    return return_from_results_benchmark;
}

The function used to determine whether a number is prime: (tested, it works, can't change)

constexpr bool is_prime_trial_division(unsigned const& n)
{
  using std::sqrt;

  if (n < 2)
    return false;

  auto const sqrt_n = isqrt(n);
  bool retval = true;
  for (unsigned i=2; i <= sqrt_n && retval; ++i)
    retval &= (n % i != 0);
  return retval;
}

The definition of results_benchmark(): (in header file, can't change)

//  benchmark_results
// This function will call op(args...) num_iters times returning the results
// as a benchmark_results structure...
//
template <typename Op, typename... Args>
constexpr auto results_benchmark(
  std::size_t const& num_iters, Op&& op, Args&&... args
) ->
  benchmark_results< std::invoke_result_t<Op, Args...> >
{
  using namespace std;
  using namespace std::chrono;

  benchmark_results< std::invoke_result_t<Op, Args...> > retval;
  for (size_t i{}; i != num_iters; ++i)
  {
    do_not_optimize_barrier();

    auto time0 = steady_clock::now();
    do_not_optimize_barrier();
    
    if constexpr(!is_void_v<decltype(op(args...))>)
      retval.results.push_back(op(args...));
    else
      op(args...);

    do_not_optimize_barrier();
    auto time1 = steady_clock::now();
    do_not_optimize_barrier();
    retval.time += duration<double>(time1-time0).count();
  }
  return retval;
}

In main, I call do_work():

auto s = do_work(std::execution::seq, &v);

If I don't call do_work(), prog.cpp compiles. I compile with the following options enabled:

g++ -std=c++20 -Wall -Wextra -Wold-style-cast -Werror -pthread -o prog.exe prog.cpp -ltbb

My questions:

  1. The main issue is the no matching function for call.... Why does my function call not work?

How do I fix it without changing this:

template <typename ExecPolicy, typename Container>
auto do_work(ExecPolicy& ep, Container const& v)
  1. I don't need to use the parameters passed to do_work anywhere else, only to pass them to the lambda function. But when compiling, there's a warning(error) unused parameter for both. How do I fix this without changing the structure of do_work?

I've tried the following (...and probably more):

  • changing the do_work() call
auto s = do_work(std::execution::seq, &v); //or
auto s = do_work(std::execution::seq, *v); //or
auto s = do_work(std::execution::seq, v);  //or

auto sq = std::execution::seq;
auto s = do_work(sq, &v);

const auto sq = std::execution::seq;
auto s = do_work(&sq, &v);
  • changing the lambda's parameters
[&](ExecPolicy ep, Container v){...}
[](ExecPolicy& ep, Container& v){...}
[&](auto& ep, auto& v){...}
[&](auto ep, auto v){...}
            
  • changing the call to count_if
count_if(ep, std::begin(v), std::end(v), is_prime_trial_division); 
count_if(ep, std::begin(v), std::end(v), is_prime_trial_division());
count_if(ep, std::begin(v), std::end(v), is_prime_trial_division(7));


Solution 1:[1]

The function signature of results_benchmark is

template <typename Op, typename... Args>
constexpr auto results_benchmark(
  std::size_t const& num_iters, Op&& op, Args&&... args
) -> benchmark_results<std::invoke_result_t<Op, Args...>>

when you invoke it in the do_work function body

results_benchmark(3, 
  [&](auto ep, auto v){
    return count_if(ep, begin(v), end(v), is_prime_trial_division);
  }
);

The value of num_iters is 3, Op is deduced as a lambda type that accepts two arguments, and Args... is empty pack.

Since you specify the return type of results_benchmark as benchmark_results<std::invoke_result_t<Op, Args...>>, this will make invoke_result unable to deduce the return type of Op because Args... is the empty pack and Op expects to take two arguments.

Try this

results_benchmark(3,
  [&] {
    return std::count_if(ep, begin(v), end(v), is_prime_trial_division);
  }
);

Demo

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1