装饰器的类方法

Fom*_*aut 6 c++

假设我有一个函数(装饰器)来测量给定函数的持续时间:

#include <unistd.h>

void measure(void (*f)()) {
    time_t tBegin = time(NULL);
    f();
    time_t tEnd = time(NULL);
    cout << "Duration: " << (tEnd - tBegin) << " sec" << endl;
}
Run Code Online (Sandbox Code Playgroud)

我想测量一个类的方法的持续时间.例如:

class Myclass {
private:
    double _d;

public:
    Myclass(double d) : _d(d) {}

    void run() {
        measure(m);
    }

    void m() const {
        usleep(1000000 * _d);
    }
};

int main() {
    Myclass obj(2.0);
    obj.run();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这样的实现会导致错误:

error: invalid use of non-static member function
Run Code Online (Sandbox Code Playgroud)

有没有一种方法在C++中正确实现它?它应该不修改外部函数measure,并且测量的方法完全是非静态的(它使用实例的数据).测量应该在方法内部run.

我需要C++ 1998/2003标准的解决方案.

R S*_*ahu 3

  1. 更改measure为函数模板以允许您使用任何可调用函数,而不仅仅是函数。

  2. 在 中使用 lambda 函数run


#include <iostream>
#include <time.h>
#include <unistd.h>

template <typename F>
void measure(F f) {
    time_t tBegin = time(NULL);
    f();
    time_t tEnd = time(NULL);
    std::cout << "Duration: " << (tEnd - tBegin) << " sec" << std::endl;
}

class Myclass {
private:
    double _d;

public:
    Myclass(double d) : _d(d) {}

    void run() {
        measure([=](){m();});
    }

    void m() const {
        usleep(1000000 * _d);
    }
};

int main() {
    Myclass obj(2.0);
    obj.run();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

由于不允许修改measure,因此您可以使用辅助类模板和函数模板来使您可以使用任何可调用对象。

#include <iostream>
#include <time.h>
#include <unistd.h>

void measure(void (*f)()) {
    time_t tBegin = time(NULL);
    f();
    time_t tEnd = time(NULL);
    std::cout << "Duration: " << (tEnd - tBegin) << " sec" << std::endl;
}

template <typename F>
struct MeasureFunctor
{
   static F* f_;
   static void run(){(*f_)();}
};

template <typename F> F* MeasureFunctor<F>::f_ = nullptr;

template <typename F>
void measure(F f) {
   MeasureFunctor<F>::f_ = &f;
   measure(MeasureFunctor<F>::run);
}

class Myclass {
private:
    double _d;

public:
    Myclass(double d) : _d(d) {}

    void run() {
        measure([=](){m();});
    }

    void m() const {
        usleep(1000000 * _d);
    }
};

int main() {
    Myclass obj(2.0);
    obj.run();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)