Decorator for a class method

Suppose I have a function (decorator) that measures the duration of a 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 class method. For instance:

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 an implementation leads to an error:

error: invalid use of non-static member function

Is there a way in C ++ to implement it correctly? It should not change the external function measure, and the measured method is non-stationary (it uses instance data). The measurement must be inside the method run.

I need a solution for the C ++ 1998/2003 standard.

+4
source share
3 answers

Since you mentioned that you were stuck in C ++ 03, the answer is that without changing the signature methodyou are stuck in some statictomfoolery:

, , lambda ++ 11 ( - const , void). , .

, :

template<class T, void(T::*PTR)()const, size_t I>
struct bind_member
{
    typedef void(*fn_type)();
    explicit bind_member(const T* _ptr) 
    {
        ptr = _ptr;
    }
    static void func(void)
    {
        (ptr->*PTR)();
    }
    operator fn_type()
    {
        return &func;
    }
    private:
    static const T*  ptr;
};

template<class T, void(T::*PTR)()const, size_t I>
const T* bind_member<T, PTR, I>::ptr = NULL;

Live Demo


bind_member struct (template<class T, void(T::*PTR)()const, size_t I>)

  • T - , - . Myclass
  • void(T::*PTR)()const const member T. PTR
  • size_t I , Myclass lambda , , , . ( , 0 /).

bind_member , . static.

func, , Myclass::m. m int, , func. , , .

: bind_member C,

typedef void(*fn_type)();
operator fn_type()
{
    return &func;
}

, func static, -. typedef func, void.

Myclass:

void run() 
{
    bind_member<Myclass, &Myclass::m, 0> b(this);
    measure(b);
}

, , bind_member, this , bind_member (m). &Myclass::m , - , , , .

, b measure, .

++ 11 ( ), , , . measure , Myclass::m. , .

+2
  • measure , , .

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

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

lambda ( std:: function ), , :

  • m() static.
  • MyClass, MyClass, measure. , m(). , .
  • m() , _d. , _d var, m(). , MyClass.

This approach will only measure one call at a time. To make multiple calls in parallel, measure()you could use streaming local storage for the link specified in step 2.

0
source

Source: https://habr.com/ru/post/1663983/


All Articles