How to ensure that every method of a class calls some other method first?

Thanks to the unusual properties of operator ->, we can inject code before any member access, at the expense of a slightly bent syntax:

// Nothing special in Foo
struct Foo {
    void a() { }
    void b() { }
    void c() { }
};

struct LoggingFoo : private Foo {
    void log() const { }

    // Here comes the trick
    Foo const *operator -> () const { log(); return this; }
    Foo       *operator -> ()       { log(); return this; }
};

Usage looks as follows:

LoggingFoo f;
f->a();

See it live on Coliru


This a minimal (but pretty general) solution to the wrapper problem:

#include <iostream>
#include <memory>

template<typename T, typename C>
class CallProxy {
    T* p;
    C c{};
public:
    CallProxy(T* p) : p{p} {}
    T* operator->() { return p; } 
};

template<typename T, typename C>
class Wrapper {
    std::unique_ptr<T> p;
public:
    template<typename... Args>
    Wrapper(Args&&... args) : p{std::make_unique<T>(std::forward<Args>(args)...)} {}
    CallProxy<T, C> operator->() { return CallProxy<T, C>{p.get()}; } 
};

struct PrefixSuffix {
    PrefixSuffix() { std::cout << "prefix\n"; }
    ~PrefixSuffix() { std::cout << "suffix\n"; }
};

struct MyClass {
    void foo() { std::cout << "foo\n"; }
};


int main()
{
    Wrapper<MyClass, PrefixSuffix> w;
    w->foo();
}

Defining a PrefixSuffix class, with the prefix code inside its constructor and the suffix code inside the destructor is the way to go. Then, you can use the Wrapper class (using the -> to access to your original class' member functions) and prefix and suffix code will be executed for every call.

See it live.

Credits to this paper, where I found the solution.


As a side-note: if the class that has to be wrapped does not have virtual functions, one could declare the Wrapper::p member variable not as pointer, but as a plain object, then hacking a bit on the the semantic of Wrapper's arrow operator; the result is that you would have no more the overhead of dynamic memory allocation.


You may do a wrapper, something like

class Foo {
public:
    void a() { /*...*/ }
    void b() { /*...*/ }
};

class LogFoo
{
public:
    template <typename ... Ts>
    LogFoo(Ts&&... args) : foo(std::forward<Ts>(args)...) {}

    const Foo* operator ->() const { log(); return &foo;}
    Foo* operator ->() { log(); return &foo;}
private:
    void log() const {/*...*/}
private:
    Foo foo;
};

And then use -> instead of .:

LogFoo foo{/* args...*/};

foo->a();
foo->b();