Существует два способа решения этой задачи.
Принять функцию (или объект функции), вернуть модифицированную функцию, которая выполняет ту же функцию, что и оригинальная функция, плюс мерывремя.Возвращаемый тип объекта не может совпадать с принятым типом параметра.Это должна быть лямбда (или пользовательский тип класса, но лямбда проще).Фактическое измерение выполняется, когда вызывается возвращенный объект.Пример использования синтаксиса:
result = measure(foo)(param1, param2); // variant 1
auto measured_foo = measure(foo);
result = measured_foo(param1, param2); // variant 2
Принять функцию (или объект функции) и ее параметры, вызвать ее и выполнить измерение.Тип возвращаемого значения - это тип исходной функции.Пример использования синтаксиса:
result = measure(foo, param1, param2);
Ваш measure
ближе всего ко второму варианту, единственное, что не так с ним - это объявление.Это правильный ответ:
auto measure = [](auto&& function, auto&&... parameters) -> decltype(auto)
Если быть точным, это не единственная неправильная вещь.Если измеренная функция возвращает ссылку, тип возврата будет неправильным.Чтобы это исправить, замените
const auto returnValue = ...
на
decltype(auto) returnValue = ...
в теле лямбды
Другая вещь, которая не подходит вашей программе (но не measure
само по себе) - это способ, которым вы пытаетесь использовать функцию-член.
Function function = instance.computation;
Это просто не работает.Используйте лямбду или std::bind
для создания связанной функции-члена.Существует около миллиона вопросов (и отличных ответов) о правильном способе сделать это в stackoverflow.
Live демо (с возвратом по ссылке работает).
Если выЧтобы получить первый способ создания измеряемой функции, выполните следующие действия:
auto measure = [](auto&& function) -> decltype(auto)
{
return [=](auto&&... parameters) mutable -> decltype(auto) {
const std::chrono::steady_clock::time_point startTimePoint =
std::chrono::steady_clock::now();
decltype(auto) result = function(std::forward<decltype(parameters)>(parameters)...);
const std::chrono::steady_clock::time_point stopTimePoint =
std::chrono::steady_clock::now();
const std::chrono::duration<double> timeSpan = std::chrono::duration_cast<
std::chrono::duration<double>>(stopTimePoint - startTimePoint);
std::cout << "Computation took " << timeSpan.count()
<< " seconds." << std::endl;
return result;
};
};
Демонстрационная версия (с возвратом по ссылке).
Обратите особое внимание на религиозное использованиеdecltype(auto)
.Также mutable
во второй версии.