В связи с необходимость часто применять CRTP сделал для себя следующий helper.
Пример использования:
template<typename derived_t>
class A : public crtp_t<A, derived_t>
{
public:
void f()
{
derived(this).f_impl();
}
};
Helper решает следующие задачи:
1. Форсирует, что класс derived_t является производным от А.
2. Форсирует, что класс derived_t является MDT (most derived type).
3. Предоставляет функции derived(), с помощью которых удобно конвертировать базовый класс в производный.
Код helper'а:
template<typename base_t, typename derived_t>
struct crtp_helper_t
{
struct inner_t
{
typedef base_t base;
typedef derived_t derived;
};
friend typename inner_t::base;
friend typename inner_t::derived;
crtp_helper_t() {}
};
template<typename base_t, typename derived_t>
class crtp_t : virtual private crtp_helper_t<base_t, derived_t>
{
};
template<typename base_t, typename derived_t>
derived_t& derived(crtp_t<base_t, derived_t>* self)
{
return static_cast<derived_t&>(*self);
}
template<typename base_t, typename derived_t>
derived_t const& derived(crtp_t<base_t, derived_t> const* self)
{
return static_cast<derived_t const&>(*self);
}
Может ещё кому пригодится. Комментарии приветствуются
з.ы. вопросы портирования:
Этот вариант работает под vc71/vc80/g++. Если надо, что б работал под edg c++ надо убрать выделенные typename.
При использовании лучше пистаь не:
class A : public crtp_t<A, derived_t>
а:
class A : public crtp_t<A<derived_t>, derived_t>
т.к. глупая vc80 иначе не понимает (vc71 как ни странно понимает)