![]() |
От: |
remark
|
http://www.1024cores.net/ |
Дата: | 02.10.07 08:06 | ||
Оценка: | 52 (10) |
struct null_t {};
typedef void(null_t::*mf_t)();
struct CRTP_base
{
void init(mf_t f) {}
void fini(mf_t f) {}
};
template<typename derived_t, typename base_t = CRTP_base>
struct CRTP : base_t
{
void init(mf_t f = 0)
{
mf_t ff = (mf_t)&derived_t::do_init;
this->base_t::init(ff);
// проверяем на предмет, что в классе не определена функция do_init
if (ff != f) static_cast<derived_t*>(this)->do_init();
}
void fini(mf_t f = 0)
{
mf_t ff = (mf_t)&derived_t::do_fini;
// проверяем на предмет, что в классе не определена функция do_fini
if (ff != f) static_cast<derived_t*>(this)->do_fini();
this->base_t::fini(ff);
}
};
struct A : CRTP<A>
{
void do_init() {std::cout << __FUNCTION__ << std::endl;}
void do_fini() {std::cout << __FUNCTION__ << std::endl;}
};
struct B : CRTP<B, A>
{
void do_init() {std::cout << __FUNCTION__ << std::endl;}
void do_fini() {std::cout << __FUNCTION__ << std::endl;}
};
struct C : CRTP<C, B>
{
void do_init() {std::cout << __FUNCTION__ << std::endl;}
void do_fini() {std::cout << __FUNCTION__ << std::endl;}
};
void test()
{
A().init();
A().fini();
std::cout << std::endl;
B().init();
B().fini();
std::cout << std::endl;
C().init();
C().fini();
std::cout << std::endl;
}
A::do_init
A::do_fini
A::do_init
B::do_init
B::do_fini
A::do_fini
A::do_init
B::do_init
C::do_init
C::do_fini
B::do_fini
A::do_fini
A::do_init
A::do_fini
A::do_init
A::do_fini
A::do_init
C::do_init
C::do_fini
A::do_fini
class Some
{
//...
void some(handler_t inner, some_param_t& some_param)
{
// some object on stack
mutex_lock l (m);
try
{
some_preaction();
// call function from derived class here!
inner(); // <-------------------------------------
some_postaction();
}
catch (...)
{
handle_exceptions();
}
}
//...
};
#include <string>
#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>
typedef boost::function<void()> handler_t;
struct null_t {};
typedef void (null_t::*fp)();
void null_f() {}
struct msg_base
{
int i;
};
struct dialog_base;
template<typename derived_t, typename base_t = dialog_base>
struct dialog : public base_t
{
template<typename msg_t>
handler_t create_handler(handler_t h, msg_t& m, fp p)
{
// проверяем, определена ли в derived_t функция on_msg()
void (derived_t::*f)(handler_t, msg_t&) = &derived_t::on_msg;
if (p == (fp)f)
// если нет, то просто передаём управление базовому классу
return base_t::create_handler(h, m, (fp)f);
// если определена, то создаём для неё функтор, и передаём в базовый класс уже его
handler_t hh = boost::bind(f, static_cast<derived_t*>(this), h, boost::ref(m));
return base_t::create_handler(hh, m, (fp)f);
}
template<typename msg_t>
void handle_msg(msg_t& m)
{
// рекурсивно оборачиваем пустой функтор в функции on_msg
handler_t hh = create_handler(handler_t(null_f), m, 0);
// вызываем
hh();
}
};
// самый базовый не шаблонный класс
struct dialog_base
{
template<typename msg_t>
handler_t create_handler(handler_t h, msg_t& m, fp p)
{
// здесь прерываем рекурсию по созданию функторов обработки
return h;
}
template<typename msg_t>
void on_msg(handler_t h, msg_t& m)
{
// здесь просто вызываем функтор
h();
}
};
// далее пользовательские диалоги и сообщения
struct base : dialog<base>
{
// обработчик для всех сообщений
template<typename msg_t>
void on_msg(handler_t h, msg_t& m)
{
std::cout << __FUNCTION__ << " - " << m.i++ << std::endl;
h();
}
};
struct derived1 : dialog<derived1, base>
{
// обработчик для всех сообщений
template<typename msg_t>
void on_msg(handler_t h, msg_t& m)
{
std::cout << __FUNCTION__ << " - " << m.i++ << std::endl;
h();
}
};
struct my_msg1 : msg_base
{
int x;
my_msg1()
{
i = 100;
x = 200;
}
};
struct my_msg2 : msg_base
{
std::string y;
my_msg2()
{
i = 500;
y = "qwerty";
}
};
struct derived2 : dialog<derived2, derived1>
{
// обработчик для всех сообщений
template<typename msg_t>
void on_msg(handler_t h, msg_t& m)
{
std::cout << __FUNCTION__ << " - " << m.i++ << std::endl;
h();
}
// а здесь определяем обработчик для конкретного типа сообщения,
// соотв. имеем доступ к его членам
void on_msg(handler_t h, my_msg2& m)
{
std::cout << __FUNCTION__ << "(my_msg2) - " << m.i++ << " - " << m.y << std::endl;
h();
}
};
struct derived3 : dialog<derived3, derived2>
{
// обработчик для всех сообщений
template<typename msg_t>
void on_msg(handler_t h, msg_t& m)
{
std::cout << __FUNCTION__ << " - " << m.i++ << std::endl;
h();
}
// а здесь определяем обработчик для конкретного типа сообщения,
// соотв. имеем доступ к его членам
void on_msg(handler_t h, my_msg1& m)
{
std::cout << __FUNCTION__ << "(my_msg1) - " << m.i++ << " - " << m.x << std::endl;
h();
}
};
int main()
{
derived2().handle_msg(my_msg1());
std::cout << std::endl;
derived3().handle_msg(my_msg1());
std::cout << std::endl;
derived3().handle_msg(my_msg2());
std::cout << std::endl;
}
base::on_msg — 100
derived1::on_msg — 101
derived2::on_msg — 102
base::on_msg — 100
derived1::on_msg — 101
derived2::on_msg — 102
derived3::on_msg(my_msg1) — 103 — 200
base::on_msg — 500
derived1::on_msg — 501
derived2::on_msg(my_msg2) — 502 — qwerty
derived3::on_msg — 503