Generic C++ function wrapping

268 views Asked by At

I am tying to write a simple generic smart pointer template that allows a programmer to apply an arbitrary number of wraps before and after calling some function FUNC() e.g. If a requirement was to start timer, lock, log_start, FUNC(), log_end, unlock , stop timer

Then I would like to be able to write something simple where the programmer supplied 3 types and a function to a template and let the compiler do the rest. I get the feeling it can be done using variadic templates in a manner similar to how typelists worked combined with overloading operator ->

i.e.

class timer {}; // ctor start timer, dtor stop timer
class locker{}; // ctor lock, dtor unlock
class logger{}; // ctor lock, dtor unlock

Then some code such as

template <typename ...base_class_list> 
class aggregate : public base_class_list... {};
using pre_conditions = aggregate<logger, locker, trans>;

class gadget 
{
    auto do_something() -> void;
}; // gadget

Finally (the part I would like to write but don’t know how to glue it together

SMART_PTR<pre_conditions, gadget> g;
g->do_something();

I can get it working easily enough using the approach described by Bjarne Stroustrup in “Wrapping C++ Member Function Calls”, but was wondering if there was a more generic and elegant solution.

1

There are 1 answers

3
Jarod42 On BEST ANSWER

The easy way is to wrapping only all operator():

template <typename T, typename ... Ts>
struct magic
{
    T obj;

    template <typename ... Us>
    decltype(auto) operator ()(Us...args)
    {
        ordered_tuple<Ts...> t; // tuple doesn't guaranty order
        obj(std::forward<Us>(args)...);
    }
};

Demo

To wrap operator ->, it is more tricky:

template <typename T, typename ... Ts>
class wrapper
{
    ordered_tuple<Ts...> t; // tuple doesn't guaranty order
    T* obj;
public:
    wrapper(T* obj) : obj(obj) {}

    T* operator ->()
    {
        return obj;
    }
};

template <typename T, typename ... Ts>
class magic
{
    T obj;
public:
    wrapper<T, Ts...> operator ->()
    {
        return {&obj};
    }
};

Demo

Handling const and non-default constructor should also be done. (and finding better name).