Reputation: 210525
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;
CEditT
defined with a template base class?In other words, in what scenario would CEditT<T>
ever be instantiated where T
is not CWindow
?
Upvotes: 4
Views: 1153
Reputation: 38912
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).
Upvotes: 2
Reputation: 90015
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.
Upvotes: 3
Reputation: 308206
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.
Upvotes: 1
Reputation: 58598
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
.
Upvotes: 2