With \"hooking\" I mean the ability to non-intrusively override the behavior of a function. Some examples:
If you're talking about causing a new method to be called before/after a function body, without changing the function body, you can base it on this, which uses a custom shared_ptr deleter to trigger the after-body function. It cannot be used for try/catch, since the before and after need to be separate functions using this technique.
Also, the version below uses shared_ptr, but with C++11 you should be able to use unique_ptr to get the same effect without the cost of creating and destroying a shared pointer every time you use it.
#include
#include
#include
#include
template
class base_wrapper
{
protected:
typedef T wrapped_type;
Derived* self() {
return static_cast(this);
}
wrapped_type* p;
struct suffix_wrapper
{
Derived* d;
suffix_wrapper(Derived* d): d(d) {};
void operator()(wrapped_type* p)
{
d->suffix(p);
}
};
public:
explicit base_wrapper(wrapped_type* p) : p(p) {};
void prefix(wrapped_type* p) {
// Default does nothing
};
void suffix(wrapped_type* p) {
// Default does nothing
}
boost::shared_ptr operator->()
{
self()->prefix(p);
return boost::shared_ptr(p,suffix_wrapper(self()));
}
};
template
class timing_wrapper : public base_wrapper< T, timing_wrapper >
{
typedef base_wrapper< T, timing_wrapper > base;
typedef boost::chrono::time_point > time_point;
time_point begin;
public:
timing_wrapper(T* p): base(p) {}
void prefix(T* p)
{
begin = boost::chrono::system_clock::now();
}
void suffix(T* p)
{
time_point end = boost::chrono::system_clock::now();
std::cout << "Time: " << (end-begin).count() << std::endl;
}
};
template
class logging_wrapper : public base_wrapper< T, logging_wrapper >
{
typedef base_wrapper< T, logging_wrapper > base;
public:
logging_wrapper(T* p): base(p) {}
void prefix(T* p)
{
std::cout << "entering" << std::endl;
}
void suffix(T* p)
{
std::cout << "exiting" << std::endl;
}
};
template class wrapper, typename T>
wrapper make_wrapper(T* p)
{
return wrapper(p);
}
class X
{
public:
void f() const
{
sleep(1);
}
void g() const
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main () {
X x1;
make_wrapper(&x1)->f();
make_wrapper(&x1)->g();
return 0;
}