Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: dynamic_cast and GUIs

77 views
Skip to first unread message

Melzzzzz

unread,
Oct 27, 2016, 6:46:29 PM10/27/16
to
On 27 Oct 2016 22:36:26 GMT
r...@zedat.fu-berlin.de (Stefan Ram) wrote:

> In 2006, Bjarne Stroustrup wrote this:
>
> »The dynamic_cast<T*>(p) converts p to the desired type
> T *if* p really is a T or a class derived from T;
> otherwise, the value of dynamic_cast<T*>(p) is 0. This
> use of dynamic_cast is the essential operation of a GUI
> callback. Thus, C++'s RTTI can be seen as the minimal
> facility for supporting a GUI.«.
>
> I really can't get it. How is a "downcast" (if I may say so)
> the "essential operation of a GUI callback"?
>
> I have written GUI callbacks in C, C++, Java and JavaScript,
> and usually they did not require a downcast.

If callback has argument(s) one need downcast. In C void pointer is
used in C++ I guess some base class...

--
press any key to continue or any other to quit

Alf P. Steinbach

unread,
Oct 27, 2016, 7:10:33 PM10/27/16
to
On 28.10.2016 00:36, Stefan Ram wrote:
> In 2006, Bjarne Stroustrup wrote this:
>
> »The dynamic_cast<T*>(p) converts p to the desired type
> T *if* p really is a T or a class derived from T;
> otherwise, the value of dynamic_cast<T*>(p) is 0. This
> use of dynamic_cast is the essential operation of a GUI
> callback. Thus, C++'s RTTI can be seen as the minimal
> facility for supporting a GUI.«.
>
> I really can't get it. How is a "downcast" (if I may say so)
> the "essential operation of a GUI callback"?

Down-conversions are necessary but usually they're accomplished simply
by calling a virtual function. The virtual call casts down the `this`
pointer.

I think Bjarne here is generalizing in an invalid way from some concrete
code that we cannot quite imagine.

But, one can simply ask him, if it matters.


> I have written GUI callbacks in C, C++, Java and JavaScript,
> and usually they did not require a downcast.
>
> The minimal facility for supporting a GUI to me would be
> access to input events from the operating system and to
> graphics.

All we have is a proposal for inclusion of a slightly modified Cairo in
the standard library, 2D graphics.

https://www.reddit.com/r/cpp/comments/1vpdkj/the_new_2d_graphics_proposal_for_the_c_standard/

I don't know what happened with it.


Cheers!,

- Alf

Paavo Helde

unread,
Oct 28, 2016, 12:59:57 PM10/28/16
to
On 28.10.2016 1:36, Stefan Ram wrote:
> In 2006, Bjarne Stroustrup wrote this:
>
> »The dynamic_cast<T*>(p) converts p to the desired type
> T *if* p really is a T or a class derived from T;
> otherwise, the value of dynamic_cast<T*>(p) is 0. This
> use of dynamic_cast is the essential operation of a GUI
> callback. Thus, C++'s RTTI can be seen as the minimal
> facility for supporting a GUI.«.
>
> I really can't get it. How is a "downcast" (if I may say so)
> the "essential operation of a GUI callback"?
>
> I have written GUI callbacks in C, C++, Java and JavaScript,
> and usually they did not require a downcast.

Some context from the same page:

"So, when the system/library hands me a pointer to a
dialog_box, how can I know whether it is one of my
Sboxs? Note that I can’t modify the library to know my
Sbox class."

So it appears he has in mind some rigid GUI frameworks where one cannot
add their own virtual functions in correct place. In this situation
dynamic_cast appears in principle as a way to emulate virtual functions.

I have worked with an old GUI program using the infamous MFC library. In
MFC you have a lot of CView pointers which point to all kind of derived
classes, but CView of course is some internal MFC base class, not
templated, and thus it is not possible to add virtual functions there.
So the app defined its own view base class containing lots of virtual
functions, and each concrete view class was multiple derived from CView
and this base class. For getting the right base class pointer
dynamic_cast was extensively used, performing a cross-cast between
multiple derivation branches this time. This worked surprisingly well,
actually.

I have understood modern GUI frameworks solve such issues in more
elegant ways, but I have no direct experience.


Richard

unread,
Oct 28, 2016, 1:16:06 PM10/28/16
to
[Please do not mail me a copy of your followup]

Paavo Helde <myfir...@osa.pri.ee> spake the secret code
<1q2dnf4oLf6fGY7F...@giganews.com> thusly:

>I have worked with an old GUI program using the infamous MFC library. In
>MFC you have a lot of CView pointers which point to all kind of derived
>classes, but CView of course is some internal MFC base class, not
>templated, and thus it is not possible to add virtual functions there.
>So the app defined its own view base class containing lots of virtual
>functions, and each concrete view class was multiple derived from CView
>and this base class. For getting the right base class pointer
>dynamic_cast was extensively used, performing a cross-cast between
>multiple derivation branches this time. This worked surprisingly well,
>actually.

I have very limited experience with MFC, so perhaps what you suggest
above is "the norm" in that community, but it feels odd to me.

My understanding of CView is that they have already provided whatever
virtual functions you need in order to implement a view with custom
behavior.

Why would you feel the need to add new virtual functions to CView?
In order to be a CView, it already has all the virtual functions it
needs.

The only reason I can think of to want to add new virtual functions
is that you have some polymorphic application behavior that you wish
to mix in with a CView.

If I wanted to have multiple views with polymorphic application behavior
that is unrelated to the responsibilties of CView, then I would be
putting that application behavior into a different class that is held
by a polymorphic base pointer in my derived view. Being a data member
in my derived view I can invoke it's polymorphic functions as necessary
inside the existing virtual overrides of methods on CView. This cleanly
separates the responsibilities of the view from the responsibilities of
my application domain. SRP all around.

All this is just a long-winded way of saying "prefer aggregation over
inheritance".[1] No dynamic cast is needed, the virtual functions on my
aggregated class just do the right thing as appropriate. My derived
CView class does it's view responsibilities and collaborates with
another polymorphic class that handles the application's
responsibilities.

<https://en.wikipedia.org/wiki/Composition_over_inheritance>
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Paavo Helde

unread,
Oct 28, 2016, 3:42:23 PM10/28/16
to
On 28.10.2016 20:15, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> Paavo Helde <myfir...@osa.pri.ee> spake the secret code
> <1q2dnf4oLf6fGY7F...@giganews.com> thusly:
>
>> I have worked with an old GUI program using the infamous MFC library. In
>> MFC you have a lot of CView pointers which point to all kind of derived
>> classes, but CView of course is some internal MFC base class, not
>> templated, and thus it is not possible to add virtual functions there.
>> So the app defined its own view base class containing lots of virtual
>> functions, and each concrete view class was multiple derived from CView
>> and this base class. For getting the right base class pointer
>> dynamic_cast was extensively used, performing a cross-cast between
>> multiple derivation branches this time. This worked surprisingly well,
>> actually.
>
> I have very limited experience with MFC, so perhaps what you suggest
> above is "the norm" in that community, but it feels odd to me.
>
> My understanding of CView is that they have already provided whatever
> virtual functions you need in order to implement a view with custom
> behavior.
>
> Why would you feel the need to add new virtual functions to CView?
> In order to be a CView, it already has all the virtual functions it
> needs.

Maybe you are right that any custom behavior should be part of
application logic and be implemented somewhere else than in view
classes. From the code I see the "extra" base class virtual functions
deal with things like drag-drop, detaching the view into a floating
frame, calculating view memory usage, etc. Not sure if this belongs to
UI or not.

> The only reason I can think of to want to add new virtual functions
> is that you have some polymorphic application behavior that you wish
> to mix in with a CView.

I suppose this is the case, there are several virtual functions that are
overridden in actual view classes. One could probably use composition
instead of inheritance, but there is still the issue with MFC functions
returning CView*.

For example, there is CFrameWnd::GetActiveView() which returns the
CView* pointer to the currently "active" or "focused" view. In the app
there may be many different view classes. They are all derived from
different MFC classes, like CTreeView, CListView, CEditView, etc. All
these view classes have some common functionality defined by my app, but
the question is how to access this functionality given the plain CView*
pointer. One option would be to use CWnd::SendMessage() with a custom
message ID, so indeed dynamic_cast could be avoided this way. Another
option, used in this app, is to dynamic_cast to the "extra" base class
and then invoke virtual or non-virtual functions on it.



Richard

unread,
Oct 28, 2016, 4:04:26 PM10/28/16
to
[Please do not mail me a copy of your followup]

Paavo Helde <myfir...@osa.pri.ee> spake the secret code
<J8idnRornOCLN47F...@giganews.com> thusly:

>On 28.10.2016 20:15, Richard wrote:
>> Why would you feel the need to add new virtual functions to CView?
>> In order to be a CView, it already has all the virtual functions it
>> needs.
>
>Maybe you are right that any custom behavior should be part of
>application logic and be implemented somewhere else than in view
>classes. From the code I see the "extra" base class virtual functions
>deal with things like drag-drop, detaching the view into a floating
>frame, calculating view memory usage, etc. Not sure if this belongs to
>UI or not.

It's hard to say without looking at the specific code in your code
base. I assume it isn't open source or you would have just posted a
URL for it :). I see virtual methods on CView for drag-n-drop already,
so I'm not sure why you'd need more for that. If we look at the
description for CView in MSDN:

"CView and its derived classes are child windows that represent
the client area of a frame window. Views show data and accept
input for a document."

I don't think docking and undocking are not the responsibility of
the view; that feels more like the responsibility of the frame.

Allow me to be clear: I'm not saying the code you have doesn't work,
but it doesn't sound like the stuff was implemented where it fits in
with MFC's model of what the different classes are supposed to do.

This has been my general experience with the presence of
dynamic_cast<>. Most of the time it is your code whispering in your
ear that it really wants to live somewhere other than where you've
put the dynamic_cast<>.

>For example, there is CFrameWnd::GetActiveView() which returns the
>CView* pointer to the currently "active" or "focused" view. In the app
>there may be many different view classes. They are all derived from
>different MFC classes, like CTreeView, CListView, CEditView, etc. All
>these view classes have some common functionality defined by my app, but
>the question is how to access this functionality given the plain CView*
>pointer. One option would be to use CWnd::SendMessage() with a custom
>message ID, so indeed dynamic_cast could be avoided this way. Another
>option, used in this app, is to dynamic_cast to the "extra" base class
>and then invoke virtual or non-virtual functions on it.

It's hard to offer alternatives when we're discussing things in general
terms. SendMessage is more in line with the "tell, don't ask" principle,
if you have to do this sort of communication. It keeps the request
and the response more loosely coupled.

I would still be left asking the question of why the code in location A
cares about what kind of implementation of the view is in location B.

"Tell, Don't Ask"
<https://pragprog.com/articles/tell-dont-ask>

Mr Flibble

unread,
Oct 28, 2016, 4:05:03 PM10/28/16
to
The correct approach in this instance is to not use MFC at all: MFC is
egregious 1990s dross.

/Flibble

Paavo Helde

unread,
Oct 28, 2016, 4:45:31 PM10/28/16
to
On 28.10.2016 23:04, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> Paavo Helde <myfir...@osa.pri.ee> spake the secret code
> <J8idnRornOCLN47F...@giganews.com> thusly:
>
>> On 28.10.2016 20:15, Richard wrote:
>>> Why would you feel the need to add new virtual functions to CView?
>>> In order to be a CView, it already has all the virtual functions it
>>> needs.
>>
>> Maybe you are right that any custom behavior should be part of
>> application logic and be implemented somewhere else than in view
>> classes. From the code I see the "extra" base class virtual functions
>> deal with things like drag-drop, detaching the view into a floating
>> frame, calculating view memory usage, etc. Not sure if this belongs to
>> UI or not.
>
> It's hard to say without looking at the specific code in your code
> base. I assume it isn't open source or you would have just posted a
> URL for it :).

Yes, it's proprietary, I guess this is good for hiding the awful code
;-) Luckily, this is not a product we sell (just an in-house development
tool and an extra which we give to the customers who insist...)


> This has been my general experience with the presence of
> dynamic_cast<>. Most of the time it is your code whispering in your
> ear that it really wants to live somewhere other than where you've
> put the dynamic_cast<>.

I'm sure you are right here.

>
>> For example, there is CFrameWnd::GetActiveView() which returns the
>> CView* pointer to the currently "active" or "focused" view. In the app
>> there may be many different view classes. They are all derived from
>> different MFC classes, like CTreeView, CListView, CEditView, etc. All
>> these view classes have some common functionality defined by my app, but
>> the question is how to access this functionality given the plain CView*
>> pointer. One option would be to use CWnd::SendMessage() with a custom
>> message ID, so indeed dynamic_cast could be avoided this way. Another
>> option, used in this app, is to dynamic_cast to the "extra" base class
>> and then invoke virtual or non-virtual functions on it.
>
> It's hard to offer alternatives when we're discussing things in general
> terms. SendMessage is more in line with the "tell, don't ask" principle,
> if you have to do this sort of communication. It keeps the request
> and the response more loosely coupled.
>
> I would still be left asking the question of why the code in location A
> cares about what kind of implementation of the view is in location B.

It's not about caring the exact type, it's about being able to call the
desired virtual function (which will automatically end up in the exact
type). For calling the virtual function you need a pointer to the proper
base class, and CView base class is having only a fixed nomenclature of
virtual functions.

Cheers
Paaco

Paavo Helde

unread,
Oct 28, 2016, 4:49:41 PM10/28/16
to
On 28.10.2016 23:04, Mr Flibble wrote:
> The correct approach in this instance is to not use MFC at all: MFC is
> egregious 1990s dross.

Your advice is correct, and absolutely useless because nobody is going
to rewrite this application.

Cheers
Paavo


Mr Flibble

unread,
Oct 28, 2016, 5:00:51 PM10/28/16
to
Sucks to be you mate.

/Flibble

Richard

unread,
Oct 28, 2016, 5:54:40 PM10/28/16
to
[Please do not mail me a copy of your followup]

Paavo Helde <myfir...@osa.pri.ee> spake the secret code
<76OdnSrV0PZKJI7F...@giganews.com> thusly:
Yes, the advice is useless, but the problem here doesn't strike me
as being one that is because MFC was written in the 90s. MFC is a
creature of its time, sure, but that is just reflected in its idea
that everything is derived from CObject and we have a large
monolithic framework. ATL also dates from the 90s but uses a
different philosophy for class hierarchies.

Anyway, my interest in this discussion wasn't to just be an idiot and
say "MFC is junk from the 90s, who cares", because doing so is just
throwing the baby out with the bathwater. MFC isn't the first, nor
is it the last, application framework that considered inheritance to
be the best vehicle for reuse. Inheritance for reuse is way overdone
in any language supporting inheritance: JavaScript, Java, C#, C++,
etc.

My interest was in getting at the root of the problem. It sounded
(and still sounds) to me that an attempt was made to place a
responsibility on the view that it shouldn't have and that's why we
needed dynamic_cast<>.

If we don't stop to consider the design philosophy of the frameworks
we're using or the design principles involved when we write code, we
aren't working smarter, we're just working harder.

Paavo Helde

unread,
Oct 28, 2016, 6:13:19 PM10/28/16
to
So take the Stroustrup example in
http://stroustrup.com/hopl-almost-final.pdf: a rigid framework is giving
you a base-class pointer and you want to access the derived class. Yes,
the framework might be badly designed, yes, your need to access the
derived class might be exaggerated, yet, if you want to do so, the C++
language provides a way to do that, dynamic_cast, which is there in case
you want to use it.

This is a pragmatic approach, and the whole C++ evolution is dominated
by pragmatic approach, otherwise it would have never been as successful
as it is.

--
Cheers
Paavo



Mr Flibble

unread,
Oct 28, 2016, 6:20:14 PM10/28/16
to
90% of the time use of dynamic_cast is:

1) a code smell;
2) a design smell;
3) erroneous.

One should be coding to interfaces (why inheritance is a good thing not
a bad thing) and a good design should reflect that. Of course one
should always prefer composition to inheritance but that can also
involve interfaces and inheritance.

/Flibble

Richard

unread,
Oct 28, 2016, 7:10:48 PM10/28/16
to
[Please do not mail me a copy of your followup]

Paavo Helde <myfir...@osa.pri.ee> spake the secret code
<cbqdnasQO5jtUI7F...@giganews.com> thusly:
Yeah, I'm not saying dynamic_cast<> should be removed from the
language or that there is never a need for it.

Based on my experience, I am asserting that many times dynamic_cast<>
is telling us something besides "yeah, this screw is sticking out
from this flush surface, but if I beat on it enough with this
dynamic_cast<> hammer, I can make it seem sorta flush with the
surface". In my experience, when you're tempted to use
dynamic_cast<> it pays to step back from the details for a moment and
consider what you're doing from a design perspective. Am I following
Single Responsibility Principle? Am I following Tell, Don't Ask? Am
I implementing Poor Man's Polymorphism (switch on type)?

>This is a pragmatic approach, and the whole C++ evolution is dominated
>by pragmatic approach, otherwise it would have never been as successful
>as it is.

Pragmatism and good design principles are not opposing forces. You
do not achieve one by sacrificing the other.

Juha Nieminen

unread,
Oct 29, 2016, 1:27:15 AM10/29/16
to
Paavo Helde <myfir...@osa.pri.ee> wrote:
> So it appears he has in mind some rigid GUI frameworks where one cannot
> add their own virtual functions in correct place. In this situation
> dynamic_cast appears in principle as a way to emulate virtual functions.

How exactly would you make a less "rigid" GUI framework where you can
add new virtual functions to existing classes of the framework?

C++ doesn't offer a syntax to add new functions to an existing class,
without modifying the source code of that class (which requires
recompiling said class because it eg. changes its vtable.) It wouldn't
even be able to offer such syntax because of that requirement. (If the
implementation of the class is in a precompiled object/library, there's
no way to "recompile" it with your added virtual functions.)

In some other languages (such as Objective-C) it is actually possible
to add new methods to a class, even if you don't have access to its
source code (and all you have is a precompiled object/library file).
But the mechanisms by which this done is rather different than in C++.

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

Paavo Helde

unread,
Oct 29, 2016, 2:57:02 AM10/29/16
to
On 29.10.2016 8:27, Juha Nieminen wrote:
> Paavo Helde <myfir...@osa.pri.ee> wrote:
>> So it appears he has in mind some rigid GUI frameworks where one cannot
>> add their own virtual functions in correct place. In this situation
>> dynamic_cast appears in principle as a way to emulate virtual functions.
>
> How exactly would you make a less "rigid" GUI framework where you can
> add new virtual functions to existing classes of the framework?

I imagine this could be done via templates. CRTP?




Dombo

unread,
Oct 29, 2016, 6:28:22 AM10/29/16
to
Op 28-Oct-16 om 23:54 schreef Richard:
> Paavo Helde <myfir...@osa.pri.ee> spake the secret code
> <76OdnSrV0PZKJI7F...@giganews.com> thusly:
>
>> On 28.10.2016 23:04, Mr Flibble wrote:
>>> The correct approach in this instance is to not use MFC at all: MFC is
>>> egregious 1990s dross.
>>
>> Your advice is correct, and absolutely useless because nobody is going
>> to rewrite this application.
>
> Yes, the advice is useless, but the problem here doesn't strike me
> as being one that is because MFC was written in the 90s. MFC is a
> creature of its time, sure, but that is just reflected in its idea
> that everything is derived from CObject and we have a large
> monolithic framework. ATL also dates from the 90s but uses a
> different philosophy for class hierarchies.

It is not just different philosophy but also constraints they had to
deal with at the time. MFC is from the early nineties when the Microsoft
C++ compiler supported little more than C with classes (no templates, no
exceptions, no standard library), and the framework was still targeting
16-bit Windows running on 386 processors. ATL is from the late nineties
when the C++ dialect understood by the Microsoft compiler of that era
had much more in common with what we would consider C++ today.

As far as everything being derived from a common "object" class; this is
not unique to MFC, you see it also in Python, Java, C#...etc, where the
"object" class is roughly the equivalent of a void*.

> Anyway, my interest in this discussion wasn't to just be an idiot and
> say "MFC is junk from the 90s, who cares", because doing so is just
> throwing the baby out with the bathwater. MFC isn't the first, nor
> is it the last, application framework that considered inheritance to
> be the best vehicle for reuse. Inheritance for reuse is way overdone
> in any language supporting inheritance: JavaScript, Java, C#, C++,
> etc.

Having a common base class for all classes is partially motivated by the
limitations of these languages. For example Java and C# do not support
templates and originally did not support generics (a sort of a dumbed
down variation of templates). So for example to have reusable container
classes it helps to have everything derived from a single base class.

> My interest was in getting at the root of the problem. It sounded
> (and still sounds) to me that an attempt was made to place a
> responsibility on the view that it shouldn't have and that's why we
> needed dynamic_cast<>.
>
> If we don't stop to consider the design philosophy of the frameworks
> we're using or the design principles involved when we write code, we
> aren't working smarter, we're just working harder.

The question is what were the motivations for a framework to do things
in a certain way, and if they do still apply. In case of MFC many of its
design choices can be explained if you look at what they had to work
with at the time (a very limited subset of the C++ language as we know
it today, targeting slow hardware), however most of the choices made
back then no longer make sense today. It is disappointing to see that
today the most popular C++ GUI frameworks (Qt, WxWidgets) still clearly
have their roots in the nineties.


Mr Flibble

unread,
Oct 29, 2016, 7:30:15 AM10/29/16
to
Have you actually looked at WxWidgets? It is basically a rehash of MFC.
Avoid.

/Flibble

Dombo

unread,
Oct 29, 2016, 7:44:30 AM10/29/16
to
Op 29-Oct-16 om 13:30 schreef Mr Flibble:
I have, hence my comment. The only advantage I see WxWidgets has
compared to MFC is that it cross-platform, other that that it appears to
suck just as badly as MFC.



JiiPee

unread,
Oct 29, 2016, 12:56:33 PM10/29/16
to
On 28/10/2016 20:42, Paavo Helde wrote:
>
>
> For example, there is CFrameWnd::GetActiveView() which returns the
> CView* pointer to the

nice to see others also use MFC... I am not the onlly one.... from 1996 :)

Paavo Helde

unread,
Oct 29, 2016, 5:28:05 PM10/29/16
to
s/use/succumb/ ;-)


Öö Tiib

unread,
Oct 30, 2016, 8:30:43 AM10/30/16
to
CRTP is actually slightly more rigid (but also more efficient) than
virtual functions. It is compile-time polymorphism and so dynamic
dispatch does not work with it. It can work well in GUI because
lot of GUI has quite rigid and non-dynamic design.

There are number of ways how to achieve dynamic polymorphism without
virtual functions in C++. One example: Adding something that will be
dynamically dispatched to group of classes can be done with visitors.
Other example: Adding something that is dynamically dispatched to
individual objects can be done with function objects.

Juha Nieminen

unread,
Oct 31, 2016, 4:15:21 AM10/31/16
to
Given that the standard committee dropped support for export templates,
and that no compiler supports them, meaning that the entire framework
(which, in the case of very large frameworks, could well consist of
hundreds of thousands of lines of code) would need to be in header files.
I shudder at the idea of how long that would take to compile, every
single time...

(Also, incidentally, and in case you were thinking of *actual* templated
virtual functions, they aren't possible.)

Paavo Helde

unread,
Oct 31, 2016, 5:21:02 AM10/31/16
to
On 31.10.2016 10:15, Juha Nieminen wrote:
> Paavo Helde <myfir...@osa.pri.ee> wrote:
>> On 29.10.2016 8:27, Juha Nieminen wrote:
>>> Paavo Helde <myfir...@osa.pri.ee> wrote:
>>>> So it appears he has in mind some rigid GUI frameworks where one cannot
>>>> add their own virtual functions in correct place. In this situation
>>>> dynamic_cast appears in principle as a way to emulate virtual functions.
>>>
>>> How exactly would you make a less "rigid" GUI framework where you can
>>> add new virtual functions to existing classes of the framework?
>>
>> I imagine this could be done via templates. CRTP?
>
> Given that the standard committee dropped support for export templates,
> and that no compiler supports them, meaning that the entire framework
> (which, in the case of very large frameworks, could well consist of
> hundreds of thousands of lines of code) would need to be in header files.
> I shudder at the idea of how long that would take to compile, every
> single time...

Yes, if something can be done does not mean it should be done.

> (Also, incidentally, and in case you were thinking of *actual* templated
> virtual functions, they aren't possible.)

No, I was thinking about regular overriding of virtual functions in
derived classes. But the critics here are most probably right that using
composition would have been cleaner and easier to implement than what
was effectively an attempt to mix two class hierarchies into one.

Cheers
Paavo


Cholo Lennon

unread,
Oct 31, 2016, 9:22:39 AM10/31/16
to
I used it a lot in the nineties (even in 16 bits). I started to leave it
behind when WTL appeared. After 2004 I have never touched it again
(lucky me), so I can't believe people are still using it! (I know, I
know, software is like Highlander)

--
Cholo Lennon
Bs.As.
ARG

Lynn McGuire

unread,
Nov 1, 2016, 3:07:09 PM11/1/16
to
We still use MFC for our main window and 3 or 4 of our dialogs. All the rest of our 150+ dialogs use a custom written user interface
toolkit that we ported from Smalltalk with our dialog and data handling code.

Lynn

Richard

unread,
Nov 1, 2016, 4:41:28 PM11/1/16
to
[Please do not mail me a copy of your followup]

Paavo Helde <myfir...@osa.pri.ee> spake the secret code
<kOqdnacISduu1YnF...@giganews.com> thusly:
It's not a GUI framework, but "ATL Internals" does a really great job
at showing how you can achieve extension through CRTP.
<http://amzn.to/2ekuzPe>
0 new messages