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);
}
вопрос — как заставить работать первый вариант?
можно ли использовать какой-нибудь трюк?
Здравствуйте, 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>
Здравствуйте, 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>можно ли использовать какой-нибудь трюк?
передавать дополнительным шаблонным параметром (один раз при определении наследника)
Здравствуйте, 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> >
{
};
Оба решения разрывают циклическую зависимость определений.
Всем спасибо!
понял про 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
Здравствуйте, 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 ();
}