Я попытался написать лямбду, которая измеряет время выполнения произвольных функций.С большой помощью мне удалось это сделать для C ++ 14 и функций, имеющих возвращаемое значение, см. Измерение времени выполнения произвольных функций с помощью C ++ 14 lambda .
Тогда я хотелмой код также работает с C ++ 11, поэтому я реализовал ту же идею с шаблонными функциями.
Наконец, я понял, что этот код не работает для функций, не имеющих возвращаемого значения.Было довольно просто обобщить функции шаблона, чтобы включить измерение времени и для функций, возвращающих void.
Но я застрял, когда дело доходит до измерения лямбды.Компилятор жалуется, что необязательное возвращаемое значение, которое я хочу использовать, имеет неполный тип.Можно ли это исправить?
Вот мой код:
#include <chrono>
#include <iostream>
#include <set>
#include <boost/config.hpp>
#ifdef BOOST_NO_CXX14_GENERIC_LAMBDAS
/**
* \brief Measures the time of arbitrary function calls.
*
* This template function works with C++11 and therefore it does not use
* universal references.
*
* This is an internal helper template for functions returning void.
*
* \tparam Function function type
* \tparam Parameters parameters type
* \param enabled whether time measurement should be enabled
* \param taskName name for printing the measured time
* \param function function to measure
* \param parameters function arguments
*
* \returns return value from given function
*/
template <typename Function, typename... Parameters>
auto measure(std::true_type, bool enabled,
const std::string& taskName, Function function, Parameters... parameters) ->
decltype(function(parameters...))
{
std::chrono::steady_clock::time_point startTimePoint;
if (enabled)
{
startTimePoint = std::chrono::steady_clock::now();
}
std::forward<decltype(function)>(function)(
std::forward<decltype(parameters)>(parameters)...);
if (enabled)
{
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 << taskName << " took " << timeSpan.count() << " seconds." <<
std::endl;
}
}
/**
* \brief Measures the time of arbitrary function calls.
*
* This template function works with C++11 and therefore it does not use
* universal references.
*
* This is an internal helper template for functions returning non-void.
*
* \tparam Function function type
* \tparam Parameters parameters type
* \param enabled whether time measurement should be enabled
* \param taskName name for printing the measured time
* \param function function to measure
* \param parameters function arguments
*
* \returns return value from given function
*/
template <typename Function, typename... Parameters>
auto measure(std::false_type, bool enabled,
const std::string& taskName, Function function, Parameters... parameters) ->
decltype(function(parameters...))
{
std::chrono::steady_clock::time_point startTimePoint;
if (enabled)
{
startTimePoint = std::chrono::steady_clock::now();
}
auto returnValue =
std::forward<decltype(function)>(function)(
std::forward<decltype(parameters)>(parameters)...);
if (enabled)
{
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 << taskName << " took " << timeSpan.count() << " seconds." <<
std::endl;
}
return returnValue;
}
template <typename Function, typename... Parameters>
using ReturnType = typename std::result_of<Function(Parameters...)>::type;
/**
* \brief Measures the time of arbitrary function calls.
*
* This template function works with C++11 and therefore it does not use
* universal references.
*
* \tparam Function function type
* \tparam Parameters parameters type
* \param enabled whether time measurement should be enabled
* \param taskName name for printing the measured time
* \param function function to measure
* \param parameters function arguments
*
* \returns return value from given function
*/
template <typename Function, typename... Parameters>
auto measure(bool enabled, const std::string& taskName, Function function,
Parameters... parameters) -> decltype(function(parameters...))
{
return measure(std::is_void<ReturnType<Function, Parameters...>>{},
enabled, taskName, function, parameters...);
}
#else
/**
* \brief Measures the time of arbitrary function calls.
*
* This lambda works with C++14 and it accepts universal references.
*
* \param enabled whether time measurement should be enabled
* \param taskName name for printing the measured time
* \param function function to measure
* \param parameters function arguments
*
* \returns return value from given function
*/
auto measure = [](bool enabled, const std::string& taskName, auto&& function,
auto&&... parameters) -> decltype(auto)
{
std::chrono::steady_clock::time_point startTimePoint;
if (enabled)
{
startTimePoint = std::chrono::steady_clock::now();
}
decltype(auto) returnValue =
std::forward<decltype(function)>(function)(
std::forward<decltype(parameters)>(parameters)...);
if (enabled)
{
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 << taskName << " took " << timeSpan.count() << " seconds." <<
std::endl;
}
return returnValue;
};
#endif
int main(int, char**)
{
measure(true, "Populating Ordered Set", []()
{
std::set<int> orderedSet;
for (int i = 0; i < 1000; ++i)
{
orderedSet.insert(i);
}
});
return 0;
}
Если он скомпилирован с помощью компилятора C ++ 11 (например, g ++ с -std = gnu ++ 11), он использует функцию шаблона и поэтому хорошо работает здесь.Если он скомпилирован с помощью компилятора C ++ 14 (-std = gnu ++ 14), он использует лямбду, и поэтому я получаю это сообщение об ошибке компиляции:
..\src\Main.cpp: In instantiation of '<lambda(bool, const string&, auto:1&&, auto:2&& ...)> [with auto:1 = main(int, char**)::<lambda()>; auto:2 = {}; std::__cxx11::string = std::__cxx11::basic_string<char>]':
..\src\Main.cpp:186:10: required from here
..\src\Main.cpp:154:24: error: 'void returnValue' has incomplete type
decltype(auto) returnValue =
^~~~~~~~~~~
Большое спасибо за любую помощь.