Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
159 views
in Technique[技术] by (71.8m points)

c++ - Decorator for a class method

Supposing I have a function (a decorator) that measures the duration of given function:

#include <unistd.h>

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

And I want to measure the duration of a method of a class. For example:

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;
}

Such implementation leads to the error:

error: invalid use of non-static member function

Is there a way in C++ to implement it correctly? It's supposed not to modify the external function measure and the measured method is exactly non-static (it uses data of the instance). The measurement should be inside of the method run.

I need solution for C++ 1998/2003 Standard.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
  1. Change measure to a function template to allow you to use any callable, not just a function.

  2. Use a lambda function in 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;
}

Since, you are not allowed to modify measure, you can use a helper class template and a function template to make it possible for you to use any callable.

#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;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...