CRTP Helper
От: remark Россия http://www.1024cores.net/
Дата: 23.08.07 06:18
Оценка:
В связи с необходимость часто применять 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 как ни странно понимает)


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: CRTP Helper
От: night beast СССР  
Дата: 23.08.07 06:37
Оценка:
Здравствуйте, remark, Вы писали:

R>В связи с необходимость часто применять CRTP сделал для себя следующий helper.

R>Пример использования:

R>Helper решает следующие задачи:

R>1. Форсирует, что класс derived_t является производным от А.
R>2. Форсирует, что класс derived_t является MDT (most derived type).
R>3. Предоставляет функции derived(), с помощью которых удобно конвертировать базовый класс в производный.

R>Может ещё кому пригодится. Комментарии приветствуются


Зачем нужен crtp_helper_t?

R>При использовании лучше пистаь не:

R>
R>class A : public crtp_t<A, derived_t>
R>

R>а:
R>
R>class A : public crtp_t<A<derived_t>, derived_t>
R>

R>т.к. глупая vc80 иначе не понимает (vc71 как ни странно понимает)

глупый gcc тоже иначе не понимает.

R>
Re[2]: CRTP Helper
От: remark Россия http://www.1024cores.net/
Дата: 23.08.07 06:52
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, remark, Вы писали:


R>>В связи с необходимость часто применять CRTP сделал для себя следующий helper.

R>>Пример использования:

R>>Helper решает следующие задачи:

R>>1. Форсирует, что класс derived_t является производным от А.
R>>2. Форсирует, что класс derived_t является MDT (most derived type).
R>>3. Предоставляет функции derived(), с помощью которых удобно конвертировать базовый класс в производный.

R>>Может ещё кому пригодится. Комментарии приветствуются


NB>Зачем нужен crtp_helper_t?


Что бы форсировать MDT, надо где-то вставить виртуальное наследование.
Пользователя не хочется заставлять наследовать свой класс от crtp_t с помощью виртуального наследования.
Поэтому crtp_t наследуется от crtp_helper_t виртуально.


R>>При использовании лучше пистаь не:

R>>
R>>class A : public crtp_t<A, derived_t>
R>>

R>>а:
R>>
R>>class A : public crtp_t<A<derived_t>, derived_t>
R>>

R>>т.к. глупая vc80 иначе не понимает (vc71 как ни странно понимает)

NB>глупый gcc тоже иначе не понимает.

Значит это только vc71 умный. И edg.

R>>


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: CRTP Helper
От: night beast СССР  
Дата: 23.08.07 07:05
Оценка:
Здравствуйте, remark, Вы писали:

R>>>Может ещё кому пригодится. Комментарии приветствуются


NB>>Зачем нужен crtp_helper_t?


R>Что бы форсировать MDT, надо где-то вставить виртуальное наследование.

R>Пользователя не хочется заставлять наследовать свой класс от crtp_t с помощью виртуального наследования.
R>Поэтому crtp_t наследуется от crtp_helper_t виртуально.

для MDT конструктор базы должен быть приватным.
Re[3]: CRTP Helper
От: night beast СССР  
Дата: 23.08.07 07:16
Оценка:
Здравствуйте, remark, Вы писали:

NB>>Зачем нужен crtp_helper_t?


R>Что бы форсировать MDT, надо где-то вставить виртуальное наследование.

R>Пользователя не хочется заставлять наследовать свой класс от crtp_t с помощью виртуального наследования.
R>Поэтому crtp_t наследуется от crtp_helper_t виртуально.

и еще нужно добавить crtp_t во френды
Re[4]: CRTP Helper
От: remark Россия http://www.1024cores.net/
Дата: 23.08.07 07:26
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, remark, Вы писали:


R>>>>Может ещё кому пригодится. Комментарии приветствуются


NB>>>Зачем нужен crtp_helper_t?


R>>Что бы форсировать MDT, надо где-то вставить виртуальное наследование.

R>>Пользователя не хочется заставлять наследовать свой класс от crtp_t с помощью виртуального наследования.
R>>Поэтому crtp_t наследуется от crtp_helper_t виртуально.

NB>для MDT конструктор базы должен быть приватным.


Там у меня там вроде приватное наследование от crtp_helper_t...



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: CRTP Helper
От: remark Россия http://www.1024cores.net/
Дата: 23.08.07 07:27
Оценка:
Здравствуйте, night beast, Вы писали:

NB>Здравствуйте, remark, Вы писали:


NB>>>Зачем нужен crtp_helper_t?


R>>Что бы форсировать MDT, надо где-то вставить виртуальное наследование.

R>>Пользователя не хочется заставлять наследовать свой класс от crtp_t с помощью виртуального наследования.
R>>Поэтому crtp_t наследуется от crtp_helper_t виртуально.

NB>и еще нужно добавить crtp_t во френды


Вообще изначально у меня и был примерно такой подход — конструктор crtp_helper_t приватный и crtp_t во врендах.
А потом я сделал приватное наследование от crtp_helper_t, и вроде как стало чуть попроще/поменьше кода.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: CRTP Helper
От: night beast СССР  
Дата: 23.08.07 07:30
Оценка: 8 (1)
Здравствуйте, remark, Вы писали:

R>Здравствуйте, night beast, Вы писали:


NB>>Здравствуйте, remark, Вы писали:


R>>>>>Может ещё кому пригодится. Комментарии приветствуются


NB>>>>Зачем нужен crtp_helper_t?


R>>>Что бы форсировать MDT, надо где-то вставить виртуальное наследование.

R>>>Пользователя не хочется заставлять наследовать свой класс от crtp_t с помощью виртуального наследования.
R>>>Поэтому crtp_t наследуется от crtp_helper_t виртуально.

NB>>для MDT конструктор базы должен быть приватным.


R>Там у меня там вроде приватное наследование от crtp_helper_t...


такой код гсс и комо компилируют
struct B : A<B> {};
struct C : B {};

int main() {
    C x;
}
Re[6]: CRTP Helper
От: remark Россия http://www.1024cores.net/
Дата: 23.08.07 07:57
Оценка: 1 (1)
Здравствуйте, night beast, Вы писали:

NB>такой код гсс и комо компилируют

NB>
NB>struct B : A<B> {};
NB>struct C : B {};

NB>int main() {
NB>    C x;
NB>}
NB>


Да, действительно, облажался.
Значит надо откатиться к предыдущему варианту:

template<typename base_t, typename derived_t> class crtp_t;

template<typename base_t, typename derived_t>
class crtp_helper_t
{
    struct inner_t
    {
        typedef crtp_t<base_t, derived_t> crtp;
        typedef base_t base;
        typedef derived_t derived;
    };
    friend typename inner_t::crtp;
    friend typename inner_t::base;
    friend typename inner_t::derived;
    crtp_helper_t() {}
};

template<typename base_t, typename derived_t>
class crtp_t : virtual 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);
}



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: CRTP Helper
От: Kubroid  
Дата: 23.08.07 08:10
Оценка: +1
вопрос чайника — зачам все это надо ?
можно маленький пример, попроще. на пальцах.
Re[8]: CRTP Helper
От: remark Россия http://www.1024cores.net/
Дата: 23.08.07 13:47
Оценка:
Здравствуйте, Kubroid, Вы писали:

K>вопрос чайника — зачам все это надо ?

K>можно маленький пример, попроще. на пальцах.

http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: CRTP Helper
От: remark Россия http://www.1024cores.net/
Дата: 23.08.07 13:49
Оценка:
Здравствуйте, Kubroid, Вы писали:

K>вопрос чайника — зачам все это надо ?

K>можно маленький пример, попроще. на пальцах.

http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Curiously_Recurring_Template_Pattern


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.