ロギングってイヤですよね。
コードが汚くなるし、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でどうにかなりますが、
あのコードは書きたくないので、何か考えたいところです。