首先,我觉得这件事肯定已经有人问过了,但我所有的调查都没有结果。如果这确实是某个地方的复制品,我提前道歉。
我正在尝试对opencv中的一组函数进行大规模基准测试,为此我想编写一个小的元函数,它接受要运行的函数,其参数(根据传递的函数而变化)并基本上设置计时并循环运行该函数。
由于我计划稍后也将lambdas传递给元函数(以对函数的组合进行基准测试),所以我考虑使用
std::function
.
这是我看完后想出的密码
the parameter pack description
:
template<typename ...Ts>
void run_test(std::string test_name, int num_repeats, std::function<void(Ts...)> f, Ts... fargs)
{
std::cout << std::endl << "Starting " << test_name << std::endl;
start_timing(test_name);
for(int i=0; i<num_repeats; i++)
{
f(fargs...);
}
end_timing(num_repeats);
}
如您所见,功能已降到最低。
start_timing
和
end_timing
是超出此问题范围的简单帮助函数。
我主要打电话给:
cv::Mat out(im_in.size(), CV_8U);
run_test(
"erode 3x3",
100,
cv::erode,
im_in, out, cv::Mat::ones(3,3,CV_8U)
);
现在,如果我试图编译这个,我得到:
error: no matching function for call to 'run_test(const char [10], const int&, void (&)(cv::InputArray, cv::OutputArray, cv::InputArray, cv::Point, int, int, const Scalar&), cv::Mat&, cv::Mat&, cv::MatExpr)'
);
^
note: candidate: template<class ... Ts> void run_test(std::__cxx11::string, int, std::function<void(Ts ...)>, Ts ...)
void run_test(std::string test_name, int num_repeats, std::function<void(Ts...)> f, Ts... fargs)
^~~~~~~~
note: template argument deduction/substitution failed:
note: mismatched types 'std::function<void(Ts ...)>' and 'void (*)(cv::InputArray, cv::OutputArray, cv::InputArray, cv::Point, int, int, const Scalar&) {aka void (*)(const cv::_InputArray&, const cv::_OutputArray&, const cv::_InputArray&, cv::Point_<int>, int, int, const cv::Scalar_<double>&)}'
);
所以…我做错什么了?为什么它有类型不匹配,而不是在
Ts...
从参数列表中选择?
更新:
在写了上面最后一个问题之后,我意识到在推断
Ts.…
对于
STD::功能
因为参数位于要展开到的实际参数列表之前
Ts.…
. 所以,我修改了代码如下(本质上,我移动了
f
最后的参数):
void run_test(std::string test_name, int num_repeats, Ts... fargs, std::function<void(Ts...)> f)
{ ... }
当然,我也相应地修改了函数调用:
cv::Mat out(im_in.size(), CV_8U);
run_test(
"erode 3x3",
NUM_REPEATS,
im_in, out, cv::Mat::ones(3,3,CV_8U),
cv::erode,
);
现在,如果我编译,我会得到一个不同的错误:
error: expected primary-expression before ')' token );
误差的变化使我认为参数的顺序确实很重要。然而,这是正确的吗?如果是,我做错什么了?
更新2:
在写第一次更新的时候,我突然想到我的假设是
f
可以接受函数并将其转换为
STD::功能
可能是错的。经过快速的研究,似乎是这样。
我试着替换
std::function<void(Ts...)> f
两者兼有
auto f
和
auto& f
(与C++ 14启用编译),但
expected primary-expression
错误仍然存在。
尽管我已经做了很多研究,但我还是找不到一种方法可以让我通过依赖编译器来计算类型的函数。
我想适应C++ 17的
std::apply
显示的功能实现
here
添加我的计时循环
invoke
打电话来,但我不明白代码,所以出错的几率很高。