首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用C++14 lambda度量任意函数的执行时间

用C++14 lambda度量任意函数的执行时间
EN

Stack Overflow用户
提问于 2018-12-12 07:29:55
回答 3查看 267关注 0票数 5

我为Scott的书“有效的现代C++”第24项感到兴奋。他提到了编写C++14 lambda来记录任意函数调用所花费的时间的可能性。

我还处于早期学习C++14特性的阶段。我的尝试(Main.cpp)类似于测量成员函数调用的时间:

代码语言:javascript
复制
#include <chrono>
#include <iostream>

auto measure = [](auto&& function, auto&&... parameters) -> decltype(function)
{
    const std::chrono::steady_clock::time_point startTimePoint =
    std::chrono::steady_clock::now();

    const auto returnValue = std::forward<decltype(function)>(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 returnValue;
};

class Test
{
public:

    int computation(double dummy)
    {
        std::cout << "Received " << dummy << ". Computing..." << std::endl;

        return 123;
    }
};

int main(int, char**)
{
    Test instance;

    using Function = int (Test::*)(double);
    Function function = instance.computation;

    int result = measure(function, 1.0);

    std::cout << "Result: " << result << std::endl;

    return 0;
}

我得到以下编译错误:

代码语言:javascript
复制
..\src\Main.cpp: In function 'int main(int, char**)':
..\src\Main.cpp:43:36: error: cannot convert 'int (Test::*)(double)' to 'int' in initialization
    int result = measure(function, 1.0);
                                                                        ^
..\src\Main.cpp: In instantiation of '<lambda(auto:1&&, auto:2&& ...)> [with auto:1 = int (Test::*&)(double); auto:2 = {double}; decltype (function) = int (Test::*&)(double)]':
..\src\Main.cpp:43:36:   required from here
..\src\Main.cpp:9:69: error: must use '.*' or '->*' to call pointer-to-member function in 'std::forward<int (Test::*&)(double)>((* & function)) (...)', e.g. '(... ->* std::forward<int (Test::*&)(double)>((* & function))) (...)'
    const auto returnValue = std::forward<decltype(function)>(function)(
                                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        std::forward<decltype(parameters)>(parameters)...);
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                

显然我做错了,但我想不出怎么做才对。有人能帮我吗?非常感谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-12-12 09:15:56

处理这一任务有两种方法。

  1. 接受一个函数(或一个函数对象),返回一个修改后的函数,该函数执行原始函数所做的相同事情,并测量时间。返回的对象类型不能与接受的参数类型相同。它必须是lambda (或自定义类类型,但lambda更简单)。实际测量是在调用返回的对象时执行的。示例用法语法: 结果=测量(Foo)(param1,param2);//变体1自动measured_foo =度量值(Foo);结果= measured_foo(param1,param2);//变体2
  2. 接受函数(或函数对象)及其参数,调用它并执行度量。返回类型是原始函数的类型。示例用法语法: 结果=测量(foo,param1,param2);

您的measure最接近第二个变体,惟一错误的地方是声明。这是正确的答案:

代码语言:javascript
复制
auto measure = [](auto&& function, auto&&... parameters) -> decltype(auto)

准确地说,这并不是唯一的错误。如果度量的函数返回引用,则返回类型将是错误的。若要修复此问题,请替换

代码语言:javascript
复制
const auto returnValue = ...

使用

代码语言:javascript
复制
decltype(auto) returnValue = ...

在羔羊的身体里

程序(但不是measure本身)的另一个错误是您试图使用成员函数的方式。

代码语言:javascript
复制
Function function = instance.computation;

这是行不通的。使用lambda或std::bind创建绑定成员函数。关于堆叠溢出的正确方法,有无数个问题(和很好的答案)。

现场演示 (通过参考工作返回)。

如果您想要创建度量函数的第一种方法,下面是如何:

代码语言:javascript
复制
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

票数 2
EN

Stack Overflow用户

发布于 2018-12-12 08:41:20

不知道你想在那里做什么,但我在这里猜我做了什么,如果这就是你想做的:

代码语言:javascript
复制
#include <chrono>
#include <iostream>
#include <functional>

auto measure = [](auto function, auto&&... parameters) -> decltype(function(parameters...))
{
    const std::chrono::steady_clock::time_point startTimePoint =
    std::chrono::steady_clock::now();

    auto returnValue = function(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 returnValue;
};

class Test
{
public:

    int computation(double dummy)
    {
        std::cout << "Received " << dummy << ". Computing..." << std::endl;

        return 123;
    }
};

int main(int, char**)
{
    Test instance;

    auto func = std::bind(&Test::computation, &instance, std::placeholders::_1);

    int result = measure(func, 1.0);

    std::cout << "Result: " << result << std::endl;

    return 0;
}
票数 1
EN

Stack Overflow用户

发布于 2020-08-24 11:18:42

如果出于任何原因不喜欢接受成员函数的函数指针(请参见这里),那么好的旧宏可以帮助您。有些人建议尽量减少宏的使用,但在本例中,我发现它更直观、更易读、更容易。任何任意函数(包括对返回类型的类的公共成员函数的调用)都可以使用以下宏进行计时。

代码语言:javascript
复制
#define timefnrt(W, X, Z){\
    time_t V = time(NULL);\
    W = X;\
    time_t Y = time(NULL);\
    Z = difftime(Y, V);\
};

实时代码演示

如果该函数返回一个void,则可以对这些函数进行计时:

代码语言:javascript
复制
#define timefnvoid(X, Z){\
    time_t V = time(NULL);\
    X;\
    time_t Y = time(NULL);\
    Z = difftime(Y, V);\
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53738032

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档