没有什么可以修复错误 "No match for function call" C++

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

我这辈子都无法修复这个错误。

我正在尝试依次测量 运行 一个函数(计算向量中的素数,但这不是重点)所花费的时间,然后并行测量。还有其他头文件,但我只包含了与错误相关的代码。

错误:

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)>)’

有关错误的更多详细信息:

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)> >’

这就是我定义相关函数的方式。它需要一个整数(运行 lambda 函数的次数)和一个 lambda.

lambda 通过引用接受执行策略和向量。它只有一行:调用 count_if() 的 return 语句,我将 exec 策略、begin(v) 和 end(v) 传递给它,以及用于确定一个数字是否为质数。

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;
}

判断一个数是否为质数的函数:(已测试,有效,不可更改)

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;
}

results_benchmark()的定义:(在头文件中,不可更改)

//  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;
}

在主要部分,我调用 do_work():

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

如果我不调用 do_work(),prog.cpp 会编译。我在启用以下选项的情况下进行编译:

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

我的问题:

  1. 主要问题是no matching function for call...。为什么我的函数调用不起作用?

如何在不更改的情况下修复它:

template <typename ExecPolicy, typename Container>
auto do_work(ExecPolicy& ep, Container const& v)
  1. 我不需要在其他任何地方使用传递给 do_work 的参数,只需将它们传递给 lambda 函数即可。但是在编译时,两者都有一个警告(错误) unused parameter。如何在不更改 do_work?
  2. 结构的情况下解决此问题

我已经尝试了以下(...可能还有更多):

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);
[&](ExecPolicy ep, Container v){...}
[](ExecPolicy& ep, Container& v){...}
[&](auto& ep, auto& v){...}
[&](auto ep, auto v){...}
            
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));

results_benchmark的函数签名是

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...>>

当您在 do_work 函数体中调用它时

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

num_iters的值为3,Op推导为接受两个参数的lambda类型,Args...包.

由于你将results_benchmark的return类型指定为benchmark_results<std::invoke_result_t<Op, Args...>>,这会使invoke_result无法推导出[=16的return类型=] 因为 Args... 是空包并且 Op 需要两个参数。

试试这个

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

Demo