CRTP - проблема
От: hobby  
Дата: 06.05.08 06:46
Оценка:
MSVC 2005

template <int A>
struct Byte
{
    static void Set (int value);
};

template <class T>
struct Impl
{
    // вариант 1.
    typedef typename T::Setter Setter; // error C2039: 'Setter' : is not a member of 'Some<A>'
    static void Set (int value) { Setter::Set (value); }

    // вариант 2 - работает
    //static void Set (int value) { typename T::Setter::Set (value); }
};

template <int A>
struct Some: Impl <Some <A> >
{
    typedef Byte <A> Setter;
};

void Test ()
{
    Some <0>::Set (0);
}


вопрос — как заставить работать первый вариант?
можно ли использовать какой-нибудь трюк?
Re: CRTP - проблема
От: _Paul Россия  
Дата: 06.05.08 07:00
Оценка:
Здравствуйте, hobby, Вы писали:

Можно например так сделать:

H>
H>template <int A>
H>struct Byte
H>{
H>    static void Set (int value);
H>};

H>template <class T>
H>struct Impl
H>{
H>    // вариант 1.
H>    struct s { typedef typename T::Setter Setter; }; // error C2039: 'Setter' : is not a member of 'Some<A>'
H>    static void Set (int value) { s::Setter::Set (value); }

H>    // вариант 2 - работает
H>    //static void Set (int value) { typename T::Setter::Set (value); }
H>};

H>template <int A>
H>struct Some: Impl <Some <A> >
H>{
H>    typedef Byte <A> Setter;
H>};

H>void Test ()
H>{
H>    Some <0>::Set (0);
H>}

H>
Re: CRTP - проблема
От: night beast СССР  
Дата: 06.05.08 07:03
Оценка:
Здравствуйте, hobby, Вы писали:

H>MSVC 2005


H>template <int A>
H>struct Byte
H>{
H>    static void Set (int value);
H>};

H>template <class T, typename S = typename T::Setter>
H>struct Impl
H>{
H>    // вариант 1.
H>    typedef S Setter; // error C2039: 'Setter' : is not a member of 'Some<A>'
H>    static void Set (int value) { Setter::Set (value); }

H>    // вариант 2 - работает
H>    //static void Set (int value) { typename T::Setter::Set (value); }
H>};

H>template <int A>
H>struct Some: Impl <Some <A>, Byte <A> >
H>{
H>//    typedef Byte <A> Setter;
H>};

H>void Test ()
H>{
H>    Some <0>::Set (0);
H>}


H>вопрос — как заставить работать первый вариант?


проблема в том что в месте 1 тип T incomplete. тот есть применять его типы или другим образом инстанцировать его ты не можешь.

H>можно ли использовать какой-нибудь трюк?


передавать дополнительным шаблонным параметром (один раз при определении наследника)
Re: CRTP - проблема
От: remark Россия http://www.1024cores.net/
Дата: 06.05.08 07:05
Оценка:
Здравствуйте, hobby, Вы писали:

H>MSVC 2005


H>вопрос — как заставить работать первый вариант?

H>можно ли использовать какой-нибудь трюк?

Непосредственно в таком виде нельзя, т.к. тут у тебя получается бесконечная рекурсия в определениях Some и Impl (циклическая зависимость определений).
Поэтому для CRTP правило такое — в определении Impl *нельзя* использовать определение Some, можно использовать только само имя Some как форвард объявление. А вот в определениях методов Impl уже можно использовать определение Some, т.к. это не вносит циклической зависимости в определения.


Вариант решения 1:
template <class T>
struct Impl
{
    struct Inner
    {
        // вариант 1.
        typedef typename T::Setter Setter; // error C2039: 'Setter' : is not a member of 'Some<A>'
        static void Set (int value) { Setter::Set (value); }
    };

    // вариант 2 - работает
    //static void Set (int value) { typename T::Setter::Set (value); }
};

void Test ()
{
    Some<0>::Inner::Set (0);
}



Вариант решения 2:
template <class T, typename Setter>
struct Impl
{
    // вариант 1.
    static void Set (int value) { Setter::Set (value); }
};

template <int A>
struct Some: Impl <Some <A>, Byte <A> >
{
};



Оба решения разрывают циклическую зависимость определений.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: CRTP - проблема
От: hobby  
Дата: 06.05.08 08:11
Оценка:
Всем спасибо!

понял про incomplete, а мне нужно именно, чтобы Impl знал типы из Some
доп. параметр в шаблоне — не подходит, там не только Setter, еще всякое,
в частности, и тип параметра для Set, и тип возврата для Get.
цель — минимизировать к-во действий при написании структур, подобных Some.

вобщем, решил внешним хелпером:

template <class T>
struct Impl
{
    typedef typename T::Setter Setter;
    typedef typename Setter::SetType SetType;
    static void Set (SetType value) { Setter::Set (value); }

    typedef typename T::Getter Getter;
    typedef typename Getter::GetType GetType;
    static GetType Get () { return Getter::Get (); }
};

template <int A>
struct SomeHelper
{
    typedef Byte <A> Setter;
    typedef Bit <A+1, 1> Getter;
};

template <int A>
struct Some: Impl <SomeHelper <A> > {};

void Test ()
{
    Some <0>::Set (0);
    bool b = Some<0>::Get ();
}


, хотя это уже не CRTP
Re[2]: CRTP - проблема
От: night beast СССР  
Дата: 06.05.08 08:31
Оценка:
Здравствуйте, hobby, Вы писали:

H>Всем спасибо!


H>понял про incomplete, а мне нужно именно, чтобы Impl знал типы из Some

H>доп. параметр в шаблоне — не подходит, там не только Setter, еще всякое,
H>в частности, и тип параметра для Set, и тип возврата для Get.
H>цель — минимизировать к-во действий при написании структур, подобных Some.

incomplete только тип наследника. то есть если передал Setter и Getter доп. параметрами, то использовать их внутренние типы можно.

в данном конкретном примере CRTP действительно не нужен

он может пригодится когда у тебе нужно добиться полиморфизма без виртуальных функций.
template<typename E>
typename E::result_type eval ( Impl<E /*,defaults used*/ > const & expr ) {
   return derived<E> (expr).eval ();
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.