Pregunta

I'm having a lot of trouble understanding the purpose of templates in ATL/WTL code.

When you look at WTL, you see code like:

template <class TBase>
class CEditT : public TBase
{
    ...
};

typedef CEditT<ATL::CWindow> CEdit;

Why is CEditT defined with a template base class?

In other words, in what scenario would CEditT<T> ever be instantiated where T is not CWindow?

¿Fue útil?

Solución

It's so that you can override methods in ATL::CWindow that are called by the ATL/WTL class. If there's something that you don't like in ATL::CWindow, you can derive a class from ATL::CWindow with overridden methods, and then pass along your new class as TBase.

For example, ATL::CWindow::CenterWindow for a long while had a bug where it did not properly account for multiple monitors, and I've seen people use this technique to override CenterWindow with a fixed implementation.

Otros consejos

Suppose composition were used instead:

template <class TBase> class CEditT {
public:
  TBase base;
  ...
};

This is not very different from something like:

template <class ITEM> class ListNode {
public:
   ITEM item;
   ListNode<ITEM> *next;
   // ...
};

ListNode could instead inherit ITEM, like CEditT does with TBase, but the drawback would be that then ITEM could not be a basic type like int. On the other hand, a ListNode would then be a kind of ITEM, which could be useful. Furthermore, it would have access to any protected: parts of ITEM.

It's so that it can take advantage of the Curiously Recurring Template Pattern. If you create a derived class of CEditT your definition would be class CMyEdit : public CEditT<CMyEdit>. By statically casting its this pointer to your class, CEditT can call your methods without having to use a vtable.

Why does everything use a template base class in ATL/WTL?

In nutshell, to achieve a "weird form of compile-time polymorphism" thanks to a design pattern (rather C++ idiom) one may call "upside-down inheritance" as technique to "specify the base class of a base class" in order to "allows you to insert your own classes into the class hierarchy" to achieve flexibility of specialising types "without hard-coding implementation to any particular derived class".

This all should become clear after reading the excellent article ATL and Upside-Down Inheritance - Understanding ATL's atypical design approach written by Jim Beveridge and published by Visual C++ Developers Journal in July, 1999. Here is link to full not paginated copy of the same article (also in the Wayback Machine).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top