読者です 読者をやめる 読者になる 読者になる

vtable版Type Erasureでコードに直接現れないロギング

C++

ロギングってイヤですよね。


コードが汚くなるし、1行しか処理がないのに
関数の出入りをロギングするために3行になってしまったり。
こういうときに、コードに直接現れない侵入的なロギングが必要だなと思います。


聞くところによると、それはAOPの動機にもなってるんだとか。
聞くところによると、それはBoost.Interfacesの動機にもなってるんだとか。


つまりこういうことですね。

#include <iostream>
#include <string>
#include <boost/noncopyable.hpp>

class log : boost::noncopyable {
public:
    static log& instance()
    {
        static log this_;
        return this_;
    }

    void out(const std::string& s) const
    {
        std::cout << "  " << s << std::endl;
    }
};

struct hoge {
    void foo() const
    {
        std::cout << "foo" << std::endl;
    }

    void bar() const
    {
        std::cout << "bar" << std::endl;
    }
};

struct Hogeable {
    struct vtable{
        void (*foo)(const void*);
        void (*bar)(const void*);
    };

    template <class T>
    struct vtable_initializer {
        static vtable vtbl_;

        static void foo(const void* this_)
        {
            log::instance().out("entry : foo function");
            static_cast<T const*>(this_)->foo();
            log::instance().out("exit  : foo function");
        }

        static void bar(void const *this_)
        {
            log::instance().out("entry : bar function");
            static_cast<T const*>(this_)->bar();
            log::instance().out("exit  : bar function");
        }
    };

    template <class T>
    Hogeable(T& obj)
        : this_(&obj), vptr_(&vtable_initializer<T>::vtbl_) {}

    void foo() const { vptr_->foo(this_); }
    void bar() const { vptr_->bar(this_); }

    void* this_;
    vtable* vptr_;
};

template <class T>
Hogeable::vtable Hogeable::vtable_initializer<T>::vtbl_ = {
    &Hogeable::vtable_initializer<T>::foo,
    &Hogeable::vtable_initializer<T>::bar
};

void piyo(Hogeable obj)
{
    obj.foo();
    obj.bar();
}

int main()
{
    hoge h;
    piyo(h);
}
entry : foo function
  foo
exit  : foo function
entry : bar function
  bar
exit  : bar function

はい、ロギングと実際の処理を切り離せましたね。
コード量が多いのはBoost.Interfacesでどうにかなりますが、
あのコードは書きたくないので、何か考えたいところです。