Здравствуйте, Аноним, Вы писали:
А>Добрый день. После долго программирования ATL соорудил следующую конструкцию.
А>А>template<typename T>
А>struct Base
А>{
А> typename T::X m_x;
А> void foo()
А> {
А> ((T *)this)->bar();
А> }
А>};
А>struct A : public Base<A>
А>{
А> typedef int X;
А> void bar()
А> {
А> }
А>};
А>
А>По идее это обязывает в структуре A определить тип данных X, а переменная этого типа будет определена в предке. Использоваться m_x будет в потомке. Понимаю, что изврат, но это не компилируется. Функции потомка можно использовать при шаблонном наследовании, а типы — нет. Почему?
Почему, уже вроде объяснили. Пригодится ли, но есть такое решение:
template<typename T>
struct ATraits
{};
template<typename T>
struct Base
{
typename ATraits<T>::X m_x;
void foo()
{
((T *)this)->bar();
}
};
class A;
template<>
struct ATraits<A>
{
typedef int X;
};
struct A : public Base<A>
{
typedef ATraits<A>::X X;
void bar()
{
}
};
Здравствуйте, rg45, Вы писали:
R>Очень опасная строчка:
R>R> ((T *)this)->bar();
R>
R>С ее помошью легко можно привести к типу, вовсе не являющемуся потомком.
R>Гораздо безопаснее так:
R>R> static_cast<T*>(this)->bar();
R>
R>В таком случае от ошибки убережет компилятор.
Не спасает от извращенного способа прострелить себе ногу по невнимательности.
template< class Derived >
struct Base
{
void f()
{
static_cast< Derived* >( this )->DoF();
}
};
struct a1 : public Base< a1 >
{
void DoF()
{
LOGF();
};
};
struct a2 : public Base< a1 >
{
};
int main()
{
a2 a;
a.f();
}