【发布时间】:2020-08-09 11:17:04
【问题描述】:
我想创建一个benchmark 函数,给定一个可调用对象及其参数,该函数将为给定可调用对象的执行计时并返回测量的std::chrono::duration<...> 以及调用可调用对象返回的值。
我在完美转发调用返回的值时遇到问题。目前我返回调用返回的值,并使用引用参数返回持续时间:
using bench_clock = std::conditional_t<std::chrono::high_resolution_clock::is_steady,
std::chrono::high_resolution_clock, std::chrono::steady_clock>;
decltype(auto) benchmark(
bench_clock::duration& duration, auto&& func, auto&&... args)
{
auto begin{ bench_clock::now() };
decltype(auto) result{
std::invoke(
std::forward<decltype(func)>(func),
std::forward<decltype(args)>(args)...)
};
duration = bench_clock::now() - begin;
return result;
}
据我所知,这完美地转发了调用返回的值。
我更愿意以传统方式返回持续时间,例如,使用std::tuple 虽然我不确定如何完美地转发返回的值。
我的猜测是像这样使用std::invoke_result_t:
using bench_clock = std::conditional_t<
std::chrono::high_resolution_clock::is_steady,
std::chrono::high_resolution_clock, std::chrono::steady_clock>;
auto benchmark(auto&& func, auto&&... args)
{
auto begin{ bench_clock::now() };
decltype(auto) result{
std::invoke(
std::forward<decltype(func)>(func),
std::forward<decltype(args)>(args)...)
};
auto duration{ bench_clock::now() - begin };
return std::tuple<std::invoke_result_t<decltype(func), decltype(args)...>, bench_clock::duration>{std::forward<decltype(result)>(result), duration};
//------------------------------------------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ is this needed?
}
我不确定这种方法是否正确完美地向前推进。我也不知道在std::tuple构造函数中是否需要使用std::forward。
还有一个问题,如果invocable返回void,则无法使用元组,因为std::tuple<void>无法实例化。
我不知道如何解决这个问题。
【问题讨论】:
-
不是
std::forward()forresult,而是std::move() -
对于
void的问题...你可以使用C++17还是只使用C++11/C++14? -
result是一个左值,不能完美转发。充其量它可以移动到元组中,但不会就地构建。如果是重对象,最好用结果构造元组,然后分配duration部分,希望NRVO发生。
标签: c++ templates return c++17 perfect-forwarding