如何将非静态成员函数指针传递给 C++ 中的模板函数?

How to pass non-static member function pointer to a template function in C++?

我正在尝试在接受通用函数指针和打包参数的头文件中创建一个函数模板。函数模板将使用打包参数调用接收到的函数指针。我的目标是计算并 return 函数指针的执行时间。

#ifndef LOGTIME_HPP
#define LOGTIME_HPP

#include <chrono>
#include <ratio>

template<typename Function, typename... Args>
double getExecutionTime(Function&& function, Args&&... args) {
    auto t1 = std::chrono::high_resolution_clock::now();
    std::invoke(std::forward<Function>(function), std::forward<Args>(args)...);
    auto t2 = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double, std::milli> ms = t2 - t1;
    return ms.count();
}

#endif

这似乎只适用于不是 classstruct 的成员函数的函数指针。这是一些使用函数模板的示例代码:

#include <iostream>
#include <thread>
#include <random>

#include "LogTime.hpp" // header including getExecutionTime()

class Obj
{
public:
    int testFunc(int dur, int num) {
        std::cout << "test" << num;
        for (int i = 0; i < dur; i++) {
            std::cout << ".";
            std::this_thread::sleep_for(std::chrono::milliseconds(1));
        }
        return 2;
    }
};

int testFunc(int dur, int num) {
    std::cout << "test" << num;
    for (int i = 0; i < dur; i++) {
        std::cout << ".";
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
    }
    return 1;
}

int main()
{
    std::random_device dev;
    std::mt19937 rng(dev());
    std::uniform_int_distribution<> uniform_dist(1, 100);

    Obj obj = Obj();

    for (int i = 0; i < 10; i++) {
        int rand = uniform_dist(rng);
        std::cout << "elapsed: "
            // this works
            << getExecutionTime(testFunc, uniform_dist(rng), i) << std::endl;
            
            // this doesn't work 
            << getExecutionTime(Obj::testFunc, uniform_dist(rng), i) << std::endl;
    }
}

我的问题是 Obj::testFunc 失败了。我知道如果 Obj::testFunc 是静态的,那么该函数会执行得很好。我通过传递 class 类型的实例来读取 std::invoke can invoke a member function 。但是,我不知道如何将其合并到功能模板中(我以前从未使用过模板)。

如果有任何帮助或见解,我将不胜感激。

非静态成员函数有一个class类型的隐式参数作为函数的第一个参数,它是映射到this指针的对象。这意味着你需要传递一个 class 类型的对象作为成员函数指针 like

之后的第一个参数
<< getExecutionTime(&Obj::testFunc, obj, uniform_dist(rng), i) << std::endl;

或者您可以使用 lambda 代替

<< getExecutionTime([&](){ obj.testFunc(uniform_dist(rng), i); }) << std::endl;