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

RAII design question

274 views
Skip to first unread message

Gareth Owen

unread,
Jun 12, 2017, 4:59:10 PM6/12/17
to
I had a timer class that measure the duration of its own existence.

In Semi-Pseudo code it looked like this.

typedef long long Time;

class Timer {
private:
Time start_time;
Time& total_time;
}

Timer::Timer(Time& tot) : start_time(gettimeofday()), total_time(tot)
{
}

Timer::~Timer()
{
end_time = gettimeofday();
total_time += end_time - start_time;
}

So I wanted to extend the

CancellableTimer : public Timer
{
private:
bool canceled;

public:
// if I call obj.cancel() then the destructor should
// not
void cancel(void) { canceled = true;}
}

Now, it seems to me that I can't get the derived class behaviour without
modifying the base class, because the base destructor always runs.

But it also seems that by Liskov Substitution Principle, a
CancellableTimer IS A Timer, so it'd be nice if I could extend Timer in
this way.

What am I missing?

Alf P. Steinbach

unread,
Jun 12, 2017, 6:06:54 PM6/12/17
to
Well, the Liskov substitution applies to instances of types, not to
types themselves. Or in other words, the LSP is about the behavior of
objects between their creation and destruction, not including what
happens before the object's constructor has finished, or after its
destructor has begun execution. For example, a derived class can conform
to the LSP wrt. a public base class, but require different constructor
arguments – that's OK, because it's not within the domain of the LSP.

But you are interested in what happens during destruction.

If a `Timer` has no behavior between the lifetime endpoints then the
solution simple: an is-a relationship is then meaningless, so don't derive.

I see no way to make the class derivation work without essentially
duplicating the CancellableTimer functionality up in base class Timer,
which would be meaningless except as a way to restrict the interface of
Timer.

Without class derivation, if you're happy with just wrapping an instance
of `Timer`, you can use dynamic or in-place allocation, and cancel it by
just not destroying the instance. For the dynamic allocation that would
leak memory, but you could preallocate say storage for 10 000 of them
and say OK, that's the implementation limit. With C++11 and later,
however, in-place allocation is not complex: there is alignment support.


Cheers & hth.,

- Alf

Alf P. Steinbach

unread,
Jun 12, 2017, 6:22:29 PM6/12/17
to
On 13-Jun-17 12:06 AM, Alf P. Steinbach wrote:
> On 12-Jun-17 10:59 PM, Gareth Owen wrote:
>> I had a timer class that measure the duration of its own existence.
>>
>> In Semi-Pseudo code it looked like this.
>>
>> typedef long long Time;
>>
>> class Timer {
>> private:
>> Time start_time;
>> Time& total_time;
>> }
>>
>> Timer::Timer(Time& tot) : start_time(gettimeofday()), total_time(tot)
>> {
>> }
>>
>> Timer::~Timer()
>> {
>> end_time = gettimeofday();
>> total_time += end_time - start_time;
>> }
>
[snip]
> Without class derivation, if you're happy with just wrapping an instance
> of `Timer`, you can use dynamic or in-place allocation, and cancel it by
> just not destroying the instance. For the dynamic allocation that would
> leak memory, but you could preallocate say storage for 10 000 of them
> and say OK, that's the implementation limit. With C++11 and later,
> however, in-place allocation is not complex: there is alignment support.

Sorry for that suggestion, it was dumb.

It applies to the general problem of preventing destructor execution,
but that's not what you need: it wouldn't even solve the problem.

The obvious (to you and others, but not me some little time ago)
solution is to let `CancellableTimer` just supply a different `Time`
variable to the `Timer` instance.



Cheers!,

- Alf [looking for a brick wall to bang head against]

Mr Flibble

unread,
Jun 12, 2017, 8:17:02 PM6/12/17
to
On 12/06/2017 23:06, Alf P. Steinbach wrote:
> Well, the Liskov substitution applies to instances of types, not to
> types themselves. Or in other words, the LSP is about the behavior of

Nonsense; LSP is all about types: the behaviour of a derived type when
accessed via base class reference must be the same as base class
behaviour. Types define behaviour not objects.

/Flibble

Alf P. Steinbach

unread,
Jun 12, 2017, 10:08:28 PM6/12/17
to
I think you're trolling, what with the snipping of a quote in the middle.

It may, however, be that you actually don't understand what I wrote.

In that case, study it some more, in particular the parts that you snipped.


Cheers!,

- Alf


Gareth Owen

unread,
Jun 13, 2017, 1:14:28 AM6/13/17
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> I see no way to make the class derivation work without essentially
> duplicating the CancellableTimer functionality up in base class Timer,
> which would be meaningless except as a way to restrict the interface
> of Timer.

That was the conclusion I reached (and as I had access to the base class
that what I did). But it felt like something smarter should've been
possible.

Marcel Mueller

unread,
Jun 13, 2017, 1:47:35 AM6/13/17
to
On 12.06.17 22.59, Gareth Owen wrote:
> I had a timer class that measure the duration of its own existence.
>
> In Semi-Pseudo code it looked like this.
[...]
> CancellableTimer : public Timer
> {
> private:
> bool canceled;
>
> public:
> // if I call obj.cancel() then the destructor should
> // not
> void cancel(void) { canceled = true;}
> }
>
> Now, it seems to me that I can't get the derived class behaviour without
> modifying the base class, because the base destructor always runs.
>
> But it also seems that by Liskov Substitution Principle, a
> CancellableTimer IS A Timer, so it'd be nice if I could extend Timer in
> this way.
>
> What am I missing?

There is an restriction in C++ inheritance. You can never override a
base class constructor nor destructor because at the time they are
called the object is not yet or no longer of the derived type. It is the
base type that gets con/destructed this way.

So any subclass of Timer can never /remove/ the behavior of Timer at
destruction. That's the point where the LSP is broken.


Marcel

Tim Rentsch

unread,
Jun 13, 2017, 2:59:09 AM6/13/17
to
Let me see if I can clear up some things.

First: The Liskov Substitution Principle is not a property that
automatically holds for C++ classes/subclasses. Rather it is a
design principle for defining classes and subclasses. It is
perfectly possible for a subclass in C++ not to satisfy the LSP
with respect to one (or several) of its superclasses (and in fact
is desirable in some cases but that is a topic for another day).
The point of the LSP is to give guidance for a relationship that
is nice (in certain ways) to impose between classes and their
subclasses. (Forgive me for not using the base/derived class
terminology used in C++, which still sounds funny to me after
using the original superclass/subclass terminology for so long
previously.)

Second: The Timer class you show has the property that it always
updates the total_time reference when an instance finishes. So
if we defined a subclass that somehow did /not/ do that, in fact
that subclass would violate the LSP for that behavioral property
(which seems to me like an essential property of Timer, but of
course I don't know which properties of Timer you think are the
important ones).

Third: What you want (or at least what I think you want) with
the CancellableTimer class is something that behaves like a Timer
except if the cancel() method is called, in which case it does
something different. There are two ways of thinking about this.
One is that the cancel() method is outside the Timer interface,
so whatever it does is okay, and LSP is irrelevant. The other is
that the point having CancellableTimer is to change some aspect
of Timer behavior, ie, to deliberately break the LSP.

Fourth: Finally getting back to your main question, which I
believe is How does one accomplish what is described in the last
paragraph? As you observe, given the implementation of Timer,
there is no way to avoid that final update. In other words, what
you want is to violate the LSP, but because of how references and
destructors work, you can't! To say this another way, you are
(over-)constrained by the implementation of Timer. If Timer were
implemented differently, it would be easy to write a subclass
that does what you want. But it isn't, so you can't.

What one might do about this depends on the particulars of
classes, etc, involved. But I don't know what those are
so I don't have any suggestions or advice to offer.

Does this help clear things up?

Tim Rentsch

unread,
Jun 13, 2017, 3:07:07 AM6/13/17
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

You may not like how the statement is phrased, but what he is
saying is essentially correct. The Liskov Subsitution Principle
is about a relationship between classes and their subclasses
(usually described in terms of types and subtypes, but for C++
it's classes and subclasses). That relationship is defined in
terms of the behaviors of instances of those classes and
subclasses, but the relationship proper is one between classes,
not between instances.

Tim Rentsch

unread,
Jun 13, 2017, 3:21:52 AM6/13/17
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> destructor has begun execution. [...]

The question of when "construction" finishes and "objectness" begins
is rather murky, but I believe the statement about destructors is
just wrong. What happens during destructor execution is just as
much a part of object behavior as method calls are. Suppose for
example we have a 'Foo *foo', which might actually point to a
subclass (aka derived class) of Foo. The action

delete foo;

must (under LSP) satisfy the behavioral guarantees of Foo, even
if 'foo' points to an instance of a derived class.

Alf P. Steinbach

unread,
Jun 13, 2017, 3:50:36 AM6/13/17
to
On 13-Jun-17 9:06 AM, Tim Rentsch wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>
>> On 13-Jun-17 2:16 AM, Mr Flibble wrote:
>>> On 12/06/2017 23:06, Alf P. Steinbach wrote:
>>>> Well, the Liskov substitution applies to instances of types, not to
>>>> types themselves. Or in other words, the LSP is about the behavior
>>>> of
>>>
>>> Nonsense; LSP is all about types: the behaviour of a derived type
>>> when accessed via base class reference must be the same as base
>>> class behaviour. Types define behaviour not objects.
>>
>> I think you're trolling, what with the snipping of a quote in the middle.
>>
>> It may, however, be that you actually don't understand what I wrote.
>>
>> In that case, study it some more, in particular the parts that you snipped.
>
> You may not like how the statement is phrased,

The absence of mention of sausages, as Leigh habitually post about,
doesn’t bother me in the slightest. I don’t need that kind of obvious
marker to see that the text fails to present a coherent argument.


> but what he is saying is essentially correct.

No, the “nonsense” claim is incorrect, pure nonsense.

The following paragraph of his, after the semicolon, is essentially
correct but is irrelevant to the nonsense nonsense claim.

Your claim that his nonsense nonsense claim is essentially correct, is
nonsense.


> The Liskov Subsitution Principle
> is about a relationship between classes and their subclasses
> (usually described in terms of types and subtypes, but for C++
> it's classes and subclasses). That relationship is defined in
> terms of the behaviors of instances of those classes and
> subclasses, but the relationship proper is one between classes,
> not between instances

Well, DEMONSTRATE how you think Liskov substitution applies for
constructors.

I'm not saying that what you write here is more relevant to your (in
context) claim about constructors than what Leigh wrote was relevant to
his claim, so when I ask for a demonstration it is only /assuming/ that
you were thinking of some connection between your claim and alleged
argument in favor of the claim, a connection that I just don't see.

I'm not even saying that we can't come up with something like the LSP
that involves constructors, e.g. for use in template code, but that
would be something not-quite-LSP, and not part of Barbara's work, and so
we'd better call it something else.

I'm saying that your claim here doesn't make sense to me, and so, please
demonstrate it.

Thank you.


Cheers!,

- Alf

Alf P. Steinbach

unread,
Jun 13, 2017, 4:05:52 AM6/13/17
to
The present case is one where the destructor has behavior in addition to
the language-mandated one of reversing the effect of the constructor.

So you could be right but I think it's impractical to think that way.

E.g. the lack of symmetry in that viewpoint bothers me, and I blithely
(perhaps wrongly) just /assumed/ symmetry, but then, there is some
asymmetry already in the degree to which constructors and destructors
have names, the former not at all, and the latter sort-of, and there is
asymmetry in the number of constructors and destructors for a class.


Cheers!,

- Alf

Alain Ketterlin

unread,
Jun 13, 2017, 4:29:01 AM6/13/17
to
Gareth Owen <gwo...@gmail.com> writes:

[...]
> Now, it seems to me that I can't get the derived class behaviour without
> modifying the base class, because the base destructor always runs.
>
> But it also seems that by Liskov Substitution Principle, a
> CancellableTimer IS A Timer, so it'd be nice if I could extend Timer in
> this way.

You got it reversed: a timer is a cancellable timer (the kind that you
can't cancel, or, at least where cancel has a particular meaning).

You have an instance of the Circle-Ellipse problem. See
https://en.wikipedia.org/wiki/Circle-ellipse_problem.

-- Alain.

Tim Rentsch

unread,
Jun 13, 2017, 6:06:04 AM6/13/17
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> On 13-Jun-17 9:06 AM, Tim Rentsch wrote:
>
>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>>
>>> On 13-Jun-17 2:16 AM, Mr Flibble wrote:
>>>
>>>> On 12/06/2017 23:06, Alf P. Steinbach wrote:
>>>>
>>>>> Well, the Liskov substitution applies to instances of types, not
>>>>> to types themselves. Or in other words, the LSP is about the
>>>>> behavior of
>>>>
>>>> Nonsense; LSP is all about types: the behaviour of a derived
>>>> type when accessed via base class reference must be the same as
>>>> base class behaviour. Types define behaviour not objects.
>>>
>>> I think you're trolling, what with the snipping of a quote in the
>>> middle.
>>>
>>> It may, however, be that you actually don't understand what I
>>> wrote.
>>>
>>> In that case, study it some more, in particular the parts that you
>>> snipped.
>>
>> You may not like how the statement is phrased,
>
> The absence of mention of sausages, as Leigh habitually post
> about, doesn?t bother me in the slightest. I don?t need that kind
> of obvious marker to see that the text fails to present a coherent
> argument.

He isn't giving an argument; he is simply making a statement.
The statement is about the definition of a term (ie, the Liskov
Substitution Principle). To know what that definition is we
can refer back to the papers where Barbara Liskov, and Barbara
Liskov with Jeanette Wing, introduced and formalized the
underlying ideas. Those papers are

Liskov, B. (May 1988). "Keynote address - data abstraction
and hierarchy". ACM SIGPLAN Notices. 23 (5): 17-34

Liskov, B. H.; Wing, J. M. (November 1994). A behavioral
notion of subtyping. ACM Trans. Program. Lang. Syst. 16
(6). pp. 1811-1841

I confess I haven't read these papers. What I did read is an
entry on Wikipedia, and also a couple of references it pointed
to. The Wikipedia page is here:

https://en.wikipedia.org/wiki/Liskov_substitution_principle

>> but what he is saying is essentially correct.
>
> No, the ?nonsense? claim is incorrect, pure nonsense.
>
> The following paragraph of his, after the semicolon, is
> essentially correct but is irrelevant to the nonsense nonsense
> claim.
>
> Your claim that his nonsense nonsense claim is essentially
> correct, is nonsense.

His statement agrees with how Wikipedia describes the term.
Since I have no reason to think the Wikipedia description
is wrong, I thought it appropriate to characterize his
statement as essentially correct. But please look at the
Wikipedia page and see what you think about that.


>> The Liskov Subsitution Principle
>> is about a relationship between classes and their subclasses
>> (usually described in terms of types and subtypes, but for C++
>> it's classes and subclasses). That relationship is defined in
>> terms of the behaviors of instances of those classes and
>> subclasses, but the relationship proper is one between classes,
>> not between instances
>
> Well, DEMONSTRATE how you think Liskov substitution applies for
> constructors.
>
> I'm not saying that what you write here is more relevant to your
> (in context) claim about constructors than what Leigh wrote was
> relevant to his claim, so when I ask for a demonstration it is
> only /assuming/ that you were thinking of some connection between
> your claim and alleged argument in favor of the claim, a
> connection that I just don't see.
>
> I'm not even saying that we can't come up with something like the
> LSP that involves constructors, e.g. for use in template code, but
> that would be something not-quite-LSP, and not part of Barbara's
> work, and so we'd better call it something else.
>
> I'm saying that your claim here doesn't make sense to me, and so,
> please demonstrate it.

I don't know why you hooked into constructors. Mr Flibble didn't
mention constructors. My followup didn't mention constructors.
Did you somehow think he was talking about something that he
wasn't? In any case my comment was only about the definition of
the LSP, and wasn't meant to say anything about constructors.

Tim Rentsch

unread,
Jun 13, 2017, 6:22:15 AM6/13/17
to
The biggest asymmetry between constructors and destructors is
that with constructors /the name of the class must be known/.
That property does not hold for other (non-static) member
functions, including destructors. If, instead of constructors,
factory functions are used (ie, via a parameter that is a
pointer to a factory function, which may construct a base object
or may construct a derived object), then we get back the lost
symmetry, and both construction and destruction participate in
the substitution behavioral guarantees.

Alf P. Steinbach

unread,
Jun 13, 2017, 6:49:10 AM6/13/17
to
On 13-Jun-17 12:05 PM, Tim Rentsch wrote:
> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>
>> On 13-Jun-17 9:06 AM, Tim Rentsch wrote:
>>
>>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>>>
>>>> On 13-Jun-17 2:16 AM, Mr Flibble wrote:
>>>>
>>>>> On 12/06/2017 23:06, Alf P. Steinbach wrote:
>>>>>
>>>>>> Well, the Liskov substitution applies to instances of types, not
>>>>>> to types themselves. Or in other words, the LSP is about the
>>>>>> behavior of
>>>>>
>>>>> Nonsense; LSP is all about types: the behaviour of a derived
>>>>> type when accessed via base class reference must be the same as
>>>>> base class behaviour. Types define behaviour not objects.
>>>>
>>>> I think you're trolling, what with the snipping of a quote in the
>>>> middle.
>>>>
>>>> It may, however, be that you actually don't understand what I
>>>> wrote.
>>>>
>>>> In that case, study it some more, in particular the parts that you
>>>> snipped.
>>>
>>> You may not like how the statement is phrased,
>>
>> The absence of mention of sausages, as Leigh habitually post
>> about, doesn?t bother me in the slightest. I don?t need that kind
>> of obvious marker to see that the text fails to present a coherent
>> argument.
>
> He isn't giving an argument;

He certainly gives that impression: an assertion followed by apparent
(but irrelevant) argument.


> he is simply making a statement.

That too.


> The statement is about the definition of a term (ie, the Liskov
> Substitution Principle). To know what that definition is we
> can refer back to the papers where Barbara Liskov, and Barbara
> Liskov with Jeanette Wing, introduced and formalized the
> underlying ideas. Those papers are
>
> Liskov, B. (May 1988). "Keynote address - data abstraction
> and hierarchy". ACM SIGPLAN Notices. 23 (5): 17-34
>
> Liskov, B. H.; Wing, J. M. (November 1994). A behavioral
> notion of subtyping. ACM Trans. Program. Lang. Syst. 16
> (6). pp. 1811-1841
>
> I confess I haven't read these papers.

I have, because in 2012 I started on a blog article series on the Liskov
Substution Principle, <url:
https://alfps.wordpress.com/2012/03/11/liskovs-substitution-principle-in-c/>.

Unfortunately that's where my illnesses caught up with me. I started on
an experimental horse's pill cure (that was once used for Tubercolosis)
that didn't work, plus a drawn-out series of surgery over a year or two,
so I never posted more than that first of three articles. :( It also
interfered with doing things to get reawarded my Microsoft Most Valued
Professional award. It's reawarded each year: I only got the first. :(


> What I did read is an
> entry on Wikipedia, and also a couple of references it pointed
> to. The Wikipedia page is here:
>
> https://en.wikipedia.org/wiki/Liskov_substitution_principle
>
>>> but what he is saying is essentially correct.

Yes, as you will note I told you that what he wrote after the semicolon,
was essentially correct, and irrelevant.

No contest about the correctness.

But repeating that here smacks of the very same kind irrelevancy as in
Leigh’ statement, the art of appearing to give an argument that defeats
some position, when that position has never been argued by anyone else.
It's a known, named, fallacy. It's called a Straw Man argument.


>> No, the ?nonsense? claim is incorrect, pure nonsense.
>>
>> The following paragraph of his, after the semicolon, is
>> essentially correct but is irrelevant to the nonsense nonsense
>> claim.
>>
>> Your claim that his nonsense nonsense claim is essentially
>> correct, is nonsense.
>
> His statement agrees with how Wikipedia describes the term.

I rather doubt that the Wikipedia article on nonsense agrees with
Leigh's position.


> Since I have no reason to think the Wikipedia description
> is wrong, I thought it appropriate to characterize his
> statement as essentially correct. But please look at the
> Wikipedia page and see what you think about that.

Nah, this is just bollocks. You're either not reading, or you're
pretending that you don't. I don't know which is worse, I'm sorry.


>>> The Liskov Subsitution Principle
>>> is about a relationship between classes and their subclasses
>>> (usually described in terms of types and subtypes, but for C++
>>> it's classes and subclasses). That relationship is defined in
>>> terms of the behaviors of instances of those classes and
>>> subclasses, but the relationship proper is one between classes,
>>> not between instances
>>
>> Well, DEMONSTRATE how you think Liskov substitution applies for
>> constructors.
>>
>> I'm not saying that what you write here is more relevant to your
>> (in context) claim about constructors than what Leigh wrote was
>> relevant to his claim, so when I ask for a demonstration it is
>> only /assuming/ that you were thinking of some connection between
>> your claim and alleged argument in favor of the claim, a
>> connection that I just don't see.
>>
>> I'm not even saying that we can't come up with something like the
>> LSP that involves constructors, e.g. for use in template code, but
>> that would be something not-quite-LSP, and not part of Barbara's
>> work, and so we'd better call it something else.
>>
>> I'm saying that your claim here doesn't make sense to me, and so,
>> please demonstrate it.
>
> I don't know why you hooked into constructors. Mr Flibble didn't
> mention constructors.

Exactly, and I mentioned that too: that he snipped what he quoted.

I think intentionally, to mislead readers. Such as you.

And I stated that.


> My followup didn't mention constructors.

Neither did Leigh.


> Did you somehow think he was talking about something that he
> wasn't?

No, rather the opposite: I think in your first response you genuinely
thought I had been talking about something I wasn't talking about.

But then you replied to my posting that Leigh commented on, commenting
on that very paragraph he quoted some of, showing that at that time you
did understand what I wrote.

So, if at this point you don't, again, then that's a kind of yo-yo effect.


> In any case my comment was only about the definition of
> the LSP, and wasn't meant to say anything about constructors.

Yes, I believe that. :-)


Cheers!,

- Alf

Mr Flibble

unread,
Jun 13, 2017, 12:35:10 PM6/13/17
to
On 13/06/2017 08:50, Alf P. Steinbach wrote:
> On 13-Jun-17 9:06 AM, Tim Rentsch wrote:
>> "Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:
>>
>>> On 13-Jun-17 2:16 AM, Mr Flibble wrote:
>>>> On 12/06/2017 23:06, Alf P. Steinbach wrote:
>>>>> Well, the Liskov substitution applies to instances of types, not to
>>>>> types themselves. Or in other words, the LSP is about the behavior
>>>>> of
>>>>
>>>> Nonsense; LSP is all about types: the behaviour of a derived type
>>>> when accessed via base class reference must be the same as base
>>>> class behaviour. Types define behaviour not objects.
>>>
>>> I think you're trolling, what with the snipping of a quote in the
>>> middle.
>>>
>>> It may, however, be that you actually don't understand what I wrote.
>>>
>>> In that case, study it some more, in particular the parts that you
>>> snipped.
>>
>> You may not like how the statement is phrased,
>
> The absence of mention of sausages, as Leigh habitually post about,
> doesn’t bother me in the slightest. I don’t need that kind of obvious
> marker to see that the text fails to present a coherent argument.
>
>
>> but what he is saying is essentially correct.
>
> No, the “nonsense” claim is incorrect, pure nonsense.

You explicitly stated that LSP was about objects not types which is
patently nonsense, as I correctly indicated.

/Flibble


Gareth Owen

unread,
Jun 13, 2017, 2:34:18 PM6/13/17
to
Tim Rentsch <t...@alumni.caltech.edu> writes:

> Second: The Timer class you show has the property that it always
> updates the total_time reference when an instance finishes. So
> if we defined a subclass that somehow did /not/ do that, in fact
> that subclass would violate the LSP for that behavioral property
> (which seems to me like an essential property of Timer, but of
> course I don't know which properties of Timer you think are the
> important ones).

The important ones are the ones I need today, and the less important
ones are the ones I needed yesterday and will need tomorrow.

> The other is that the point having CancellableTimer is to change some
> aspect of Timer behavior, ie, to deliberately break the LSP.

The peculiarity though, and I think it is, is that I can change many
aspect of a class's behaviour, except those in its constructor

> In other words, what you want is to violate the LSP, but because of
> how references and destructors work, you can't!



> What one might do about this depends on the particulars of
> classes, etc, involved. But I don't know what those are
> so I don't have any suggestions or advice to offer.

Oh, the solution was easy - I made the baseclass cancellable.

One alternative was to replace the reference with a pointer and cause
the cancel function to reseat the pointer to a private static garbage
variable than can never be looked at.

That seems kind of overkill though.

Another alternative was to delegate destruction to a virtual function
destroy() and a "destroyed" flag to the base class, so each class's
destructor looked like this

~SubClass() {
if(!destroyed) this->destroy();
destroyed = true;
}

Every subclass's destructor gets called, but only the most-derived one
does anything...

But this is a fire-and-forget class that I use for testing code-speed,
so all that seemed a bit much.

> Does this help clear things up?

It does. Though I'm not sure I agree 100% with your interpretation of
LSP. My CancellableTimer can be used anywhere a Timer can be used, but
the fact that I used a reference not a pointer added constraints that
should have been a mere implementation detail.

Alf P. Steinbach

unread,
Jun 13, 2017, 4:48:31 PM6/13/17
to
No, I was talking about the substitution, that the principle is about.

It's not about substituting types, such as substituting types in the C++
declaration of an object.

That was very clear the way I wrote it, but not after you successfully
trollingly quoted out of context and in new context, part of the
paragraph (indeed part of a sentence), where you sniupped that which
could inform a reader that your new context was misleading.


> as I correctly indicated.

No, you trolled.

That involves a fair bit of misdirection.


Cheers!,

- Alf

Mr Flibble

unread,
Jun 13, 2017, 7:10:52 PM6/13/17
to
Again LSP is about types not objects; objects do not define behaviours
types do. The object substitutability you speak of only applies to
objects of related types and it is the behaviours as defined by those
types that is important not the objects themselves.

/Flibble

Alf P. Steinbach

unread,
Jun 13, 2017, 8:32:01 PM6/13/17
to
You have trolled, successfully, and you have also demonstrated that you
are not familiar with the subject area, and unable to adjust. What more
do you want?


Cheers!

- Alf

Mr Flibble

unread,
Jun 13, 2017, 9:05:48 PM6/13/17
to
Oh I think I have fully demonstrated my knowledge of LSP (see my initial
reply); it is you who seems to be confused/unsure about the subject what
with you going on about constructors and object lifetimes and such which
have nothing to do with LSP per se.

/Flibble



Tim Rentsch

unread,
Jun 13, 2017, 11:07:35 PM6/13/17
to
I don't take the sentences after the semicolon as an argument,
but just an elaboration of the previous characterization (ie, the
word "Nonsense").

>> he is simply making a statement.
>
> That too.

I don't know what you mean by this statement. The two cases I am
trying to distinguish are mutually exclusive. They can't both be
true.

>> The statement is about the definition of a term (ie, the Liskov
>> Substitution Principle). To know what that definition is we
>> can refer back to the papers where Barbara Liskov, and Barbara
>> Liskov with Jeanette Wing, introduced and formalized the
>> underlying ideas. Those papers are
>>
>> Liskov, B. (May 1988). "Keynote address - data abstraction
>> and hierarchy". ACM SIGPLAN Notices. 23 (5): 17-34
>>
>> Liskov, B. H.; Wing, J. M. (November 1994). A behavioral
>> notion of subtyping. ACM Trans. Program. Lang. Syst. 16
>> (6). pp. 1811-1841
>>
>> I confess I haven't read these papers.
>
> I have, because in 2012 I started on a blog article series on the
> Liskov Substution Principle, <url:
> https://alfps.wordpress.com/2012/03/11/liskovs-substitution-principle-in-c/>.

Okay. AFAICS what you say in there agrees with what I said and
what I understand the Wikipedia page to be saying.

> Unfortunately that's where my illnesses caught up with me. I started
> on an experimental horse's pill cure (that was once used for
> Tubercolosis) that didn't work, plus a drawn-out series of surgery
> over a year or two, so I never posted more than that first of three
> articles. :( It also interfered with doing things to get reawarded my
> Microsoft Most Valued Professional award. It's reawarded each year: I
> only got the first. :(

I'm sorry to hear that. It sounds like it was a very hard time. :(

>> What I did read is an
>> entry on Wikipedia, and also a couple of references it pointed
>> to. The Wikipedia page is here:
>>
>> https://en.wikipedia.org/wiki/Liskov_substitution_principle
>>
>>>> but what he is saying is essentially correct.
>
> Yes, as you will note I told you that what he wrote after the
> semicolon, was essentially correct, and irrelevant.

Ahh, I didn't understand before what you meant in the earlier
comment. As I understand things, I believe what Mr Flibble was
saying is relevant to (some of) your earlier comments, so I don't
know why you think what he said was irrelevant, or what it was
irrelevant to. To me it does look quite relevant to your
statement upthread.

> No contest about the correctness.
>
> But repeating that here smacks of the very same kind irrelevancy as in
> Leigh? statement, the art of appearing to give an argument that
> defeats some position, when that position has never been argued by
> anyone else. It's a known, named, fallacy. It's called a Straw Man
> argument.

I don't know why you would say this. He was responding to your
statement that the LSP is about the behavior of objects. (His
quoting cut off just before the word "objects" but I thought it
was clear from context that this is what he was responding to.
Also the word "objects" was there in the posting he was
responding to.)

>>> No, the ?nonsense? claim is incorrect, pure nonsense.
>>>
>>> The following paragraph of his, after the semicolon, is
>>> essentially correct but is irrelevant to the nonsense nonsense
>>> claim.
>>>
>>> Your claim that his nonsense nonsense claim is essentially
>>> correct, is nonsense.
>>
>> His statement agrees with how Wikipedia describes the term.
>
> I rather doubt that the Wikipedia article on nonsense agrees with
> Leigh's position.

As I read what is said on the Wikipedia page on the LSP, and what
Mr Flibble (or Leigh if that is his name) has said in his
responses, what he is saying agrees with what the Wikipedia page
says about the LSP (and which is also consistent with what you
wrote in the blog entry, to the extent of what I saw there).
I'm at a loss to understand what has prompted the tone of your
response here. I've been making an effort to be cordial and
helpful, and it seems like your response is somewhat boiling over
to be rude and dismissive. I don't want to get in the middle
of some sort of conflict of personalities; my comments are only
about the statements that have been made, not about the people
who made them. I hope you can see that.

Alf P. Steinbach

unread,
Jun 13, 2017, 11:23:27 PM6/13/17
to
On 14-Jun-17 5:07 AM, Tim Rentsch wrote:
>
> I'm at a loss to understand what has prompted the tone of your
> response here.

No you're not.

- Alf

Christian Gollwitzer

unread,
Jun 14, 2017, 3:31:51 AM6/14/17
to
Am 14.06.17 um 05:23 schrieb Alf P. Steinbach:
Has your news account been hacked?

Christian

Christian Gollwitzer

unread,
Jun 14, 2017, 3:32:56 AM6/14/17
to
Am 14.06.17 um 02:31 schrieb Alf P. Steinbach:
Jerry, is it you?

Christian

Alf P. Steinbach

unread,
Jun 14, 2017, 4:30:29 AM6/14/17
to
Nope. Tim is intentionally supporting a trolling effort. The very same
paragraph he describes as nonsense in this sub-thread, he responded to
in a meaningful way, understanding it completely, in another sub-thread.

And when I pointed that out to him he /continued/. That
self-contradiction and failure to address it when mentioned, means that
he's non truthful here about not understanding anything, and I called
him out on that

I have enough with the silly attacks from the ungrateful Juha, they
annoy me sufficiently, I don't have to take this shit.


Cheers!,

- Alf

Tim Rentsch

unread,
Jun 14, 2017, 9:33:00 AM6/14/17
to
Gareth Owen <gwo...@gmail.com> writes:

> Tim Rentsch <t...@alumni.caltech.edu> writes:
>
>> Second: The Timer class you show has the property that it always
>> updates the total_time reference when an instance finishes. So
>> if we defined a subclass that somehow did /not/ do that, in fact
>> that subclass would violate the LSP for that behavioral property
>> (which seems to me like an essential property of Timer, but of
>> course I don't know which properties of Timer you think are the
>> important ones).
>
> The important ones are the ones I need today, and the less important
> ones are the ones I needed yesterday and will need tomorrow.
>
>> The other is that the point having CancellableTimer is to change some
>> aspect of Timer behavior, ie, to deliberately break the LSP.
>
> The peculiarity though, and I think it is, is that I can change many
> aspect of a class's behaviour, except those in its constructor

I am guessing you meant destructor there rather than constructor.
If so then I agree - AFAICT there is no way (short of some sort
of extra-linguistic trickery, or placement new, etc) to avoid the
base class destructor being called. And "peculiarity" does
indeed seem appropriate.

>> In other words, what you want is to violate the LSP, but because of
>> how references and destructors work, you can't!
>
>
>
>> What one might do about this depends on the particulars of
>> classes, etc, involved. But I don't know what those are
>> so I don't have any suggestions or advice to offer.
>
> Oh, the solution was easy - I made the baseclass cancellable.
>
> One alternative was to replace the reference with a pointer and cause
> the cancel function to reseat the pointer to a private static garbage
> variable than can never be looked at.
>
> That seems kind of overkill though.
>
> Another alternative was to delegate destruction to a virtual function
> destroy() and a "destroyed" flag to the base class, so each class's
> destructor looked like this
>
> ~SubClass() {
> if(!destroyed) this->destroy();
> destroyed = true;
> }
>
> Every subclass's destructor gets called, but only the most-derived one
> does anything...
>
> But this is a fire-and-forget class that I use for testing code-speed,
> so all that seemed a bit much.

Yeah. I'm surprised that C++ doesn't provide some way to avoid
calling a base class destructor, especially since it seems like
it comes up often enough (appearing on stackoverflow and lots
of other places).

>> Does this help clear things up?
>
> It does. Though I'm not sure I agree 100% with your interpretation of
> LSP. My CancellableTimer can be used anywhere a Timer can be used, but
> the fact that I used a reference not a pointer added constraints that
> should have been a mere implementation detail.

I'm pretty sure my description of LSP agrees with how it was
defined in the Liskov and Wing paper. The thing about LSP is that
it is quite stringent: subtypes can provide stronger guarantees,
but never weaker guarantees. For LSP to hold, it isn't enough
that a derived class object be usable anywhere a base class object
can be - it also must provide the same behavior that the base
class object would. The point of using a CancellableTimer is to
change some aspect of a Timer's behavior (ie, so as not to update
the referenced data), which violates what LSP requires.

Tim Rentsch

unread,
Jun 14, 2017, 11:15:15 AM6/14/17
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> On 14-Jun-17 9:31 AM, Christian Gollwitzer wrote:
>
>> Am 14.06.17 um 05:23 schrieb Alf P. Steinbach:
>>
>>> On 14-Jun-17 5:07 AM, Tim Rentsch wrote:
>>>
>>>> I'm at a loss to understand what has prompted the tone of your
>>>> response here.
>>>
>>> No you're not.
>>
>> Has your news account been hacked?
>
> Nope. Tim is intentionally supporting a trolling effort. The very same
> paragraph he describes as nonsense in this sub-thread, he responded to
> in a meaningful way, understanding it completely, in another
> sub-thread.
>
> And when I pointed that out to him he /continued/. That
> self-contradiction and failure to address it when mentioned, means
> that he's non truthful here about not understanding anything, and I
> called him out on that

In case anyone is still reading this, let me say for the record
that I don't consider Mr Flibble's posting that started all this
off to be trolling. He was making a reasonable statement in
response to a statement made by Alf. It happens that I agree
with his statement, but whether one agrees with it or not I think
it was a reasonable followup to Alf's posting.

Let me also say that my two followups to which Alf referred were
consistent with each other. If someone thinks otherwise then
they have not understood my intended meaning. I am happy to
discuss all this in a calm and rational way, if anyone is still
interested. I don't understand why Alf is having the reaction
that he is, and unfortunately that seems to preclude further
useful discussion. So for now I expect to have no more to say on
the subject, unless something happens to change that.

Gareth Owen

unread,
Jun 14, 2017, 2:38:24 PM6/14/17
to
Tim Rentsch <t...@alumni.caltech.edu> writes:

> I'm pretty sure my description of LSP agrees with how it was
> defined in the Liskov and Wing paper.

Yeah, but what do they know? It doesn't agree with my own hazy idea of
what the LSP is...

> The thing about LSP is that it is quite stringent: subtypes can
> provide stronger guarantees, but never weaker guarantees.

Yeah. I think what I got what a kind of abstraction leak - as a
disposable class I never formalised the guarantees, and my choice of
implementation gave me a much stronger guarantee than I intended
(because the reference could not be reseated, and the base destructor
could not be side-stepped.)

In effect my implementation of Timer had baked in far more behaviour
than my mental model of the class. The CancellableTimer was (in the
Liskov sense) a Timer-as-imagined, but not a Timer-as-implemented.

Alf P. Steinbach

unread,
Jun 14, 2017, 3:11:08 PM6/14/17
to
On 14-Jun-17 5:15 PM, Tim Rentsch trolled:
> I don't understand

You do.

- Alf


Alf P. Steinbach

unread,
Jun 14, 2017, 3:58:18 PM6/14/17
to
On 14-Jun-17 3:32 PM, Tim Rentsch wrote:
>
> I'm pretty sure my description of LSP agrees with how it was
> defined in the Liskov and Wing paper.

Your view is as I see it not incompatible, but as I recall Liskov & Wing
did not consider constructors and destructors (object lifetimes), which
is what your interpretation is about.

They, or at least Liskov, still as I recall, did consider generalization
(e.g. of number types) versus specialization (e.g. of animal classes),
which means that ideally one should be really careful about using the
term “subtype” in a sense that implies it is their meaning: one would
have to check the details of the various papers to be sure that was
proper. For possibly their use of the term evolved. I'm not sure.

However, we, now, have to use practical terminology.


> The thing about LSP is that
> it is quite stringent: subtypes can provide stronger guarantees,
> but never weaker guarantees. For LSP to hold, it isn't enough
> that a derived class object be usable anywhere a base class object
> can be - it also must provide the same behavior that the base
> class object would. The point of using a CancellableTimer is to
> change some aspect of a Timer's behavior (ie, so as not to update
> the referenced data), which violates what LSP requires.

Let's consider how that (in your interpretation) LSP violation could
manifest.

For this to happen there must be some code where

1) The code is unaware that the object's dynamic type is
CancellableTimer instead of the statically known Timer type.

2) The CancellableTimer::cancel method is invoked.

3) The object is destroyed.

For example, in this code:

void foo( Timer& t )
{
// Whatever.
}

there is no LSP violation, because the object isn't destroyed.

In this code:

void bar()
{
Time total;
CancellableTimer timer( total );
// ...
if( something ) { timer.cancel(); }
// ...
}

there is still no LSP violation, because the statically known type is
not Timer: there is no case of not knowing the object's contracts.

Getting the violation to manifest appears to require completely
unreasonable, contrived code like this:

// 3rd party library code:

namespace g{ CancellableTimer* pLastTimer; }

auto newTimer( Time& total ) -> Timer
{
g::pLastTimer = new CancellableTimer( total );
return g::pLastTimer;
}

void destroy( Timer* p )
{
if( p = g::pLastTimer ) { pLastTimer = nullptr; }
delete p;
}

void doUngoodThings( Timer* p )
{
if( p == g::pLastTimer ) { g::pLastTimer->cancel(); }
}

// Client code:

void xyzzy()
{
Time total;
auto pTimer = newTimer( total );
// Whatever

doUngoodThings( pTimer );

// Whatever
destroy( pTimer );
// Oooh oh! `total` has not been set, as this code expected!
}

Maybe there is some simpler code where the violation manifests, but I
think this shows that the (your interpretation) LSP violation is
contingent on pretty special cases, unreasonable client code.

I'm not entirely sure but it seems like prohibiting dynamic allocation
would be enough to remove all possible manifestions of the (in your
interpretation) LSP violation, and thereby, the violation itself.

- Alf

Tim Rentsch

unread,
Jun 22, 2017, 9:52:25 AM6/22/17
to
Gareth Owen <gwo...@gmail.com> writes:

> Tim Rentsch <t...@alumni.caltech.edu> writes:
>
>> The thing about LSP is that it is quite stringent: subtypes can
>> provide stronger guarantees, but never weaker guarantees.
>
> Yeah. I think what I got what a kind of abstraction leak - as a
> disposable class I never formalised the guarantees, and my choice of
> implementation gave me a much stronger guarantee than I intended
> (because the reference could not be reseated, and the base destructor
> could not be side-stepped.)
>
> In effect my implementation of Timer had baked in far more behaviour
> than my mental model of the class. The CancellableTimer was (in the
> Liskov sense) a Timer-as-imagined, but not a Timer-as-implemented.

Right, I understand (and had more-or-less inferred as much from
your earlier comments).

There are two things going on here, both of which I think are
noteworthy.

One is that how destructors work is wired in at a deep level in
C++, in such a way that the usual semantics is nearly impossible
to override. That together with the member variable being a
reference created an insoluble problem. I'm surprised that C++
doesn't provide a means to choose alternate semantics for how
destructors work when a subclass might want to do that. I played
around with various schemes to work around that; some were nicer
than others but I didn't find any that strike me as completely
satisfactory.

The second thing is that C++ doesn't really provide a way to
define what you want here. Or maybe a better way to say this
is that C++ does provide ways to define things like what you
want, but not what you want precisely. There are two kinds of
compatibility that C++ accommodates: interface compatibility,
and implementation compatibility. The problem is that what you
want falls somewhere in between those two endpoints.

Another way of expressing the second point is not being able to
distinguish types and classes. It's been known for more than 30
years that types and classes are not synonymous, but that
understanding hasn't yet percolated out to the community at
large. Unfortunately C++ is firmly wedded to the concept of
seeing classes as types (or sometimes the other way around)
rather than supporting the two as distinct notions. Given how
C++ has evolved it would be very difficult to change that now,
but I think it's worth starting the conversation, so that at
least the understanding will be there even if it takes the
language a while to catch up.

Mr Flibble

unread,
Jun 22, 2017, 12:25:25 PM6/22/17
to
On 22/06/2017 14:52, Tim Rentsch wrote:
> Another way of expressing the second point is not being able to
> distinguish types and classes. It's been known for more than 30
> years that types and classes are not synonymous, but that
> understanding hasn't yet percolated out to the community at
> large. Unfortunately C++ is firmly wedded to the concept of
> seeing classes as types (or sometimes the other way around)
> rather than supporting the two as distinct notions. Given how
> C++ has evolved it would be very difficult to change that now,
> but I think it's worth starting the conversation, so that at
> least the understanding will be there even if it takes the
> language a while to catch up.

What absolutely nonsense! Of course classes are types. An instance of a
type is an object, thus:

int a = 42; // a is the name of an OBJECT of scalar TYPE 'int'.
foo o = 42; // o is the name of an OBJECT of class TYPE 'foo'.

/Flibble



Alf P. Steinbach

unread,
Jun 22, 2017, 12:56:02 PM6/22/17
to
On 22-Jun-17 6:25 PM, Mr Flibble wrote:
I think Tim means that there are other things that also are types, so
that “class” is a much more specialized, less general term than “type”.

For example, even in what C++ supports, as you show, we have `enum`
types, and built-in types, and pointer and reference types, none of
which are classes.

But I suspect that Tim has now read at least one or two of the articles
by Barbara Liskov that he cited but didn't then read (and that it turned
out that I could prove that I cited and had read some five years ago,
though, unprovable, I think I first read them in the mid 1990’s), and
perhaps due to my remarks about his use of the term “subtype”, has now
gained a better appreciation of the shortcomings of the C++ type system.

For example, there is the relationship between mathematical “integer”
and “rational”, where every integer value is-a rational value, but where
there are more rationals... One way to address that in modern C++ is via
implicit conversion, instead of class inheritance. And we do that as a
matter of course for smart pointers, but I’m not entirely sure of the
connection, how this really fits in an academic view of things.

However, I think it’s possible that what Tim writes here is not
/relevant/ to the original issue of the OP.


Cheers!,

- Alf

me

unread,
Jun 22, 2017, 1:07:16 PM6/22/17
to
On Thursday, June 22, 2017 at 9:56:02 AM UTC-7, Alf P. Steinbach wrote:
<big snip>

> For example, there is the relationship between mathematical “integer”
> and “rational”, where every integer value is-a rational value, but where
> there are more rationals...
<more snip>

Well, no (to the last clause): there are exactly as many rationals as there are integers.

Alf P. Steinbach

unread,
Jun 22, 2017, 1:24:02 PM6/22/17
to
Just add “in any given range”.

Comparing infinities is a not of much practical advantage in programming. :)

What's at issue here is that a class derivation such as

struct Rational{ int a; int b; }; // Represents a/b.
struct Integer: Rational {}; // Class invariant: b == 1 always

where `Integer` is a /restriction/ on values, is not a practical
proposition.

It can however be implemented as

struct Integer { int value; };

struct Rational
{
Integer a;
Integer b;

auto operator Integer() const
{ if( b != 1 ) throw "Moo hah"; return a; }

// More ops, in particular arithmetic, plus:

Rational( Integer const value )
: a{ value }
, b{ 1 }
{}
};

And one in my view important feature of the latter design is that there
is no knowledge of `Rational` in the `Integer` class. One can devise an
unbounded number of classes, /generalizations/, like `Rational`. It
would not be practical to directly add foreknowledge of them all in
`Integer`, although perhaps some indirection could be applied, IDK.

In practice I've mostly just met this problem with `enum` generalizations.

E.g., ordinary playing card, versus the type that also admits joker cards.


Cheers!,

- Alf

Mr Flibble

unread,
Jun 22, 2017, 2:18:28 PM6/22/17
to
On 22/06/2017 17:55, Alf P. Steinbach wrote:
> On 22-Jun-17 6:25 PM, Mr Flibble wrote:
>> On 22/06/2017 14:52, Tim Rentsch wrote:
>>> Another way of expressing the second point is not being able to
>>> distinguish types and classes. It's been known for more than 30
>>> years that types and classes are not synonymous, but that
>>> understanding hasn't yet percolated out to the community at
>>> large. Unfortunately C++ is firmly wedded to the concept of
>>> seeing classes as types (or sometimes the other way around)
>>> rather than supporting the two as distinct notions. Given how
>>> C++ has evolved it would be very difficult to change that now,
>>> but I think it's worth starting the conversation, so that at
>>> least the understanding will be there even if it takes the
>>> language a while to catch up.
>>
>> What absolutely nonsense! Of course classes are types. An instance of
>> a type is an object, thus:
>>
>> int a = 42; // a is the name of an OBJECT of scalar TYPE 'int'.
>> foo o = 42; // o is the name of an OBJECT of class TYPE 'foo'.
>
> I think Tim means that there are other things that also are types, so
> that “class” is a much more specialized, less general term than “type”.

So what if other things are also types? Doesn't change the fact that
classes are types.

Perhaps Tim's issue is the way the language handles different categories
of types in different ways? Even if we view this as a shortcoming in the
language (I don't) then again it doesn't change the fact that classes
are types.

If you want to use a useless programming language like Haskell so you
can feel all warm and fuzzy with your "types" that fulfil some strict
ivory tower definition of what a "type" is then use it and fuck off from
this newsgroup with your complaining and nonsense noise.

/Flibble

me

unread,
Jun 22, 2017, 3:43:23 PM6/22/17
to
On Thursday, June 22, 2017 at 10:24:02 AM UTC-7, Alf P. Steinbach wrote:
> On 22-Jun-17 7:07 PM, me wrote:
> > On Thursday, June 22, 2017 at 9:56:02 AM UTC-7, Alf P. Steinbach wrote:
> > <big snip>
> >
> >> For example, there is the relationship between mathematical “integer”
> >> and “rational”, where every integer value is-a rational value, but where
> >> there are more rationals...
> > <more snip>
> >
> > Well, no (to the last clause): there are exactly as many rationals as there are integers.
> >
>
> Just add “in any given range”.
>

<snip>

Not if the "given range" is (0, inf) =)

Sorry, couldn't resist. Pedantry is /de riguer/ in clc.

<Looks up at message header>

Ooops, never mind, I'll get my coat.

Ian Collins

unread,
Jun 22, 2017, 4:38:48 PM6/22/17
to
On 06/23/17 04:55 AM, Alf P. Steinbach wrote:
> On 22-Jun-17 6:25 PM, Mr Flibble wrote:
>> On 22/06/2017 14:52, Tim Rentsch wrote:
>>> Another way of expressing the second point is not being able to
>>> distinguish types and classes. It's been known for more than 30
>>> years that types and classes are not synonymous, but that
>>> understanding hasn't yet percolated out to the community at
>>> large. Unfortunately C++ is firmly wedded to the concept of
>>> seeing classes as types (or sometimes the other way around)
>>> rather than supporting the two as distinct notions. Given how
>>> C++ has evolved it would be very difficult to change that now,
>>> but I think it's worth starting the conversation, so that at
>>> least the understanding will be there even if it takes the
>>> language a while to catch up.
>>
>> What absolutely nonsense! Of course classes are types. An instance of a
>> type is an object, thus:
>>
>> int a = 42; // a is the name of an OBJECT of scalar TYPE 'int'.
>> foo o = 42; // o is the name of an OBJECT of class TYPE 'foo'.
>
> I think Tim means that there are other things that also are types, so
> that “class” is a much more specialized, less general term than “type”.
>
> For example, even in what C++ supports, as you show, we have `enum`
> types, and built-in types, and pointer and reference types, none of
> which are classes.

The language its self acknowledged class being a specialised type when
"template <typename T>" replaced "template <class T>" as the standard
form. C++17 goes one step further with template template parameters.

--
Ian

Chris Vine

unread,
Jun 22, 2017, 4:50:13 PM6/22/17
to
No. Georg Cantor proved a long time ago that there are different sizes
of infinity, and inequalities of infinity, and used integers and reals
in the proof (OK, reals not rationals, but the same applies).

Gareth Owen

unread,
Jun 22, 2017, 5:13:39 PM6/22/17
to
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> writes:

> No. Georg Cantor proved a long time ago that there are different sizes
> of infinity, and inequalities of infinity, and used integers and reals
> in the proof (OK, reals not rationals, but the same applies).

There are different sizes of infinities, but the set of integers and and
the set of rationals have the same infinite cardinality
(the smallest - they are both countably infinite).

Chris Vine

unread,
Jun 22, 2017, 5:27:01 PM6/22/17
to
Are you agreeing with me, disagreeing with me, or adding verisimilitude
and corroborative detail?

As I understand it the cardinality of reals is at least as large as
that of naturals (integers), the cardinality of naturals being the
minimum infinite cardinality.

But I don't mind being wrong. I am reminded that engineers defer only
to physicists, physicists defer only to mathematicians, and
mathematicians defer only to God.

me

unread,
Jun 22, 2017, 5:47:58 PM6/22/17
to
You're correct in that the cardinality of the reals is greater than that
of the naturals (which are of the smallest infinite cardinality), but,
perhaps curiously, sets like the rationals and algebraics are also
of the same cardinality as the naturals, even though they are "dense"
like the reals.

So there are exactly the same number of rationals as of integers or of
naturals, but there are _more_ reals.

Chris Vine

unread,
Jun 22, 2017, 6:07:31 PM6/22/17
to
Thank you, that is a curiosity. This presumably arises from the fact
that rationals are expressible by two integers (as a fraction), two
being a finite number, but it is still somewhat counter intuitive.

me

unread,
Jun 22, 2017, 8:49:08 PM6/22/17
to
I'm not a mathematician by any stretch, so I'm mostly just musing here:

I'm sure a real mathematician would quibble about your "arises from"
explanation, but I think it's not unreasonable in a hand-wavey manner.

I think the algebraics extend your explanation in an interesting way.
Just like the rationals can be defined by _pairs_ of integers, the
algebraics can be defined by tuples (of finite but unbounded degree)
of integers and so form a countable set (i.e., have the same
cardinality as the naturals). But the algebraics include
many _irrational_ numbers as well, though though of course "many"
means "almost none" of the reals =)

Gareth Owen

unread,
Jun 23, 2017, 12:58:07 AM6/23/17
to
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> writes:

> On Thu, 22 Jun 2017 22:13:30 +0100
> Gareth Owen <gwo...@gmail.com> wrote:
>> Chris Vine <chris@cvine--nospam--.freeserve.co.uk> writes:
>>
>> > No. Georg Cantor proved a long time ago that there are different
>> > sizes of infinity, and inequalities of infinity, and used integers
>> > and reals in the proof (OK, reals not rationals, but the same
>> > applies).
>>
>> There are different sizes of infinities, but the set of integers and
>> and the set of rationals have the same infinite cardinality
>> (the smallest - they are both countably infinite).
>
> Are you agreeing with me, disagreeing with me, or adding verisimilitude
> and corroborative detail?

I think I'm disagreeing with you, because I *think* you suggested there
were more rationals than reals.

> As I understand it the cardinality of reals is at least as large as
> that of naturals (integers), the cardinality of naturals being the
> minimum infinite cardinality.

True. You can't put the reals and integers into one-to-one
correspondence (diagonal-slash argument).

You *can* put the rationals and integers into one-to-one correspondence
so their cardinalities are the same.

Paul Sinnett

unread,
Jun 23, 2017, 7:57:11 AM6/23/17
to
On Friday, 23 June 2017 05:58:07 UTC+1, gwowen wrote:
> Chris Vine <chris@cvine--nospam--.freeserve.co.uk> writes:
>
> > On Thu, 22 Jun 2017 22:13:30 +0100
> > Gareth Owen <gwo...@gmail.com> wrote:
> >> Chris Vine <chris@cvine--nospam--.freeserve.co.uk> writes:
> >>
> >> > No. Georg Cantor proved a long time ago that there are different
> >> > sizes of infinity, and inequalities of infinity, and used integers
> >> > and reals in the proof (OK, reals not rationals, but the same
> >> > applies).
> >>
> >> There are different sizes of infinities, but the set of integers and
> >> and the set of rationals have the same infinite cardinality
> >> (the smallest - they are both countably infinite).
> >
> > Are you agreeing with me, disagreeing with me, or adding verisimilitude
> > and corroborative detail?
>
> I think I'm disagreeing with you, because I *think* you suggested there
> were more rationals than reals.
>
> > As I understand it the cardinality of reals is at least as large as
> > that of naturals (integers), the cardinality of naturals being the
> > minimum infinite cardinality.
>
> True. You can't put the reals and integers into one-to-one
> correspondence (diagonal-slash argument).
>
> You *can* put the rationals and integers into one-to-one correspondence
> so their cardinalities are the same.

True, but I think this branch of the thread has gone into the weeds because it left the world of c++ types and entered the world of mathematical sets.

A better comparison for the intended context would be 16 bit integers compared with 32 bit integers. The second can represent all of the first and then some.

Although as an interesting aside without leaving a purely programming world: while a rational type made from two 32 bit integers can represent less distinct values than a 64 bit fixed point number made from 2 32 bit integers, it can still represent values exactly (e.g. 1/3) that the fixed point cannot.

David Brown

unread,
Jun 23, 2017, 7:59:08 AM6/23/17
to
I am a mathematician by education, but a engineer by profession.
Hopefully that is good enough :-)

> I'm sure a real mathematician would quibble about your "arises from"
> explanation, but I think it's not unreasonable in a hand-wavey manner.

It is not a bad way to think about it, IMHO.

When talking about the cardinality ("size") of infinite sets, and
comparing the size of sets A and B, you can prove them equal in two
ways. One is to figure out a bijection between them - a function "f"
that takes every "a" from "A" and maps it to exactly one "b" in "B",
covering the whole of B. The other is to find two /injections/ - a
function that takes every "a" from "A" and maps it to exactly one "b" of
"B" (but not necessarily covering all of B), and vice-versa.

An injection from the integers to the rationals is easy - every integer
is already a rational. Thus there are at least as many rationals as
integers.

To go the other way, think of your rationals as p/q where p and q are
integers (with q non-zero). Draw two axis, with p as the horizontal
axis and q as the vertical axis. Each point on this grid is a rational
p/q. Note that each rational turns up in many places - ½ will be at (1,
2), (2, 4), (-100, -200), etc. That doesn't matter. If you start at
the middle and move around the grid in a square spiral, you will pass
through each point in the grid in a finite time. For each rational, the
corresponding integer is then the distance you have gone in your spiral.
Thus there are no more rationals than there are integers.

For any given infinite cardinal ∞, and any finite integer n, there are
some odd rules of arithmetic that arise from arguments like this:

∞ + n = n + ∞ = ∞
∞ * n = n * ∞ = ∞
∞ + ∞ = ∞
∞ * ∞ = ∞
∞ ^ n = ∞

(But beware : n ^ ∞ ≠ ∞)

So combining two integers to get the rationals gives you ∞², which is
the same as ∞. (2^∞ is much bigger - it is the size of the real numbers.)

>
> I think the algebraics extend your explanation in an interesting way.
> Just like the rationals can be defined by _pairs_ of integers, the
> algebraics can be defined by tuples (of finite but unbounded degree)
> of integers and so form a countable set (i.e., have the same
> cardinality as the naturals). But the algebraics include
> many _irrational_ numbers as well, though though of course "many"
> means "almost none" of the reals =)
>

(For those that don't know, algebraic numbers are the solutions to
equations of the form a₀ + a₁·x + a₂·x² + … + a_n·x^n = 0, where n is a
finite positive integer, and all the coefficients are integers. They
are a subset of the complex numbers.)

It is not really accurate to describe the algebraic numbers as a set of
tuples, because there is no fixed size for the tuples. You could say it
is the union of a set of sets of tuples.

Proving that there are no more algebraic numbers than there are
integers, despite there being no finite limit on how long the tuples
are, is more interesting than proving the size of the rationals.


Ben Bacarisse

unread,
Jun 23, 2017, 10:03:01 AM6/23/17
to
It doesn't matter but it does mean you need to adjust the text above
since what you end up describing here:

> If you start at
> the middle and move around the grid in a square spiral, you will pass
> through each point in the grid in a finite time. For each rational, the
> corresponding integer is then the distance you have gone in your spiral.
> Thus there are no more rationals than there are integers.

is not an injection. Unless, of course, by "for each rational" you mean
"for each unique rational" in which case the spiral gives you a
bijection and you don't need to "two injections" approach.

Since you are looking only for an injection you can map p/q (in its
lowest form) to 2^p3^q and, if you need to map the negative rationals,
map -p/q to, say, 5^p3^q.

<snip>
>> I think the algebraics extend your explanation in an interesting way.

<snip>
> (For those that don't know, algebraic numbers are the solutions to
> equations of the form a₀ + a₁·x + a₂·x² + … + a_n·x^n = 0, where n is a
> finite positive integer, and all the coefficients are integers.

<snip>
> Proving that there are no more algebraic numbers than there are
> integers, despite there being no finite limit on how long the tuples
> are, is more interesting than proving the size of the rationals.

You can use the same prime power injection or simply sort the
polynomials using the normal sort order.

--
Ben.

David Brown

unread,
Jun 23, 2017, 10:29:15 AM6/23/17
to
Yes, it is an injection from each pair of integers (or grid point) to
the integers, rather than an injection from the rationals. And an
injection from each rational to the grid can be made by taking the point
corresponding to the lowest form of p/q. So really, I should have given
it as a two-step process - so much for trying to keep it simple!

> Since you are looking only for an injection you can map p/q (in its
> lowest form) to 2^p3^q and, if you need to map the negative rationals,
> map -p/q to, say, 5^p3^q.

Or alternatively, to 5 * 2^p * 3^q.

There are many ways to make such injections. A visual one with a spiral
is often easier to comprehend, but messier for calculations and rigorous
proof.

>
> <snip>
>>> I think the algebraics extend your explanation in an interesting way.
>
> <snip>
>> (For those that don't know, algebraic numbers are the solutions to
>> equations of the form a₀ + a₁·x + a₂·x² + … + a_n·x^n = 0, where n is a
>> finite positive integer, and all the coefficients are integers.
>
> <snip>
>> Proving that there are no more algebraic numbers than there are
>> integers, despite there being no finite limit on how long the tuples
>> are, is more interesting than proving the size of the rationals.
>
> You can use the same prime power injection or simply sort the
> polynomials using the normal sort order.
>

Yes, mapping the polynomial to 2^a₀ + 3^a₁ + 5^a₂ + … works nicely.
Again, there are a number of ways of doing it.

(And like the case of the rationals, this is an injection from the
integer polynomials to the integers, not an injection from the algebraic
numbers. Each algebraic number is the solution to infinitely many such
polynomials.)


leigh.v....@googlemail.com

unread,
Jun 24, 2017, 6:41:43 AM6/24/17
to
Nonsense. There are not different sizes of infinity if infinities in question are unbounded.

/Flibble

Ian Collins

unread,
Jun 24, 2017, 7:29:58 AM6/24/17
to
On 06/24/17 10:41 PM, leigh.v....@googlemail.com wrote:
> Nonsense. There are not different sizes of infinity if infinities in question are unbounded.

Who or what are yo replying to?


--
Ian

Ben Bacarisse

unread,
Jun 24, 2017, 10:12:36 AM6/24/17
to
leigh.v....@googlemail.com writes:

> Nonsense. There are not different sizes of infinity if infinities in
> question are unbounded.

As a statement in natural language, that's a defensible position. But
if you mean that all pairs of infinite sets can be put into one-to-one
correspondence with each other (the mathematician's meaning of "the same
size"), then that's false. You may choose to define a set theory in
which it is not false, but then you will have (a) a lots of work to do,
and (b) some trouble with things like power sets and real analysis.

--
Ben.

Mr Flibble

unread,
Jun 24, 2017, 10:39:21 AM6/24/17
to
Nope.

/Flibble

Ben Bacarisse

unread,
Jun 24, 2017, 11:43:36 AM6/24/17
to
What, /all/ of those statements were wrong? You /don't/ think your
statement was defensible? And you /do/ think every pair of infinite
sets can be bijected? And you /don't/ think you can define a set theory
where that is possible? At the very least, the last two are
contradictory.

Anyway, I'm happy to leave it that you disagree with something in my
post and anyone who is still reading can pick what it is they think it
might be.

--
Ben.

Gareth Owen

unread,
Jun 25, 2017, 12:07:28 PM6/25/17
to
Mr Flibble <flibbleREM...@i42.co.uk> writes:

> Nope.

Don't ever change, Leigh.

David Brown

unread,
Jun 25, 2017, 12:48:56 PM6/25/17
to
Mr. Flibble doesn't believe in maths beyond primary school level. (I
don't mean he doesn't /understand/ it - I mean he does not believe it
exists, or is useful, or that anyone else can understand and use it.)

Trying to talk to him about infinities, groups, non-Euclidean
geometries, etc., is as useful as trying to talk to a young-earther
about fossils.


Gareth Owen

unread,
Jun 25, 2017, 1:50:02 PM6/25/17
to
David Brown <david...@hesbynett.no> writes:

> Mr. Flibble doesn't believe in maths beyond primary school level. (I
> don't mean he doesn't /understand/ it - I mean he does not believe it
> exists, or is useful, or that anyone else can understand and use it.)
>
> Trying to talk to him about infinities, groups, non-Euclidean
> geometries, etc., is as useful as trying to talk to a young-earther
> about fossils.

Nicely phrased, sir.

Daniel

unread,
Jun 25, 2017, 6:26:55 PM6/25/17
to
On Saturday, June 24, 2017 at 10:39:21 AM UTC-4, Mr Flibble wrote:
>
> Nope.
>
Mr Flibble, likes to qluibble.

Vir Campestris

unread,
Jun 26, 2017, 4:43:10 PM6/26/17
to
That's qulibble.

(sorry, couldn't resist :) )
Andy

Real Troll

unread,
Jun 26, 2017, 5:36:09 PM6/26/17
to
Still doesn't look right to me!!

Either you meant: gullible
or you meant: quibble

Which is it Andy?

Öö Tiib

unread,
Jun 27, 2017, 2:29:02 AM6/27/17
to
It is just a play with words. Behaving immature and silly may amuse
but does not unfortunately bring childhood back.

scott....@gmail.com

unread,
Jun 27, 2017, 12:18:08 PM6/27/17
to
On Monday, June 12, 2017 at 4:59:10 PM UTC-4, gwowen wrote:
> I had a timer class that measure the duration of its own existence.
>
> In Semi-Pseudo code it looked like this.
>
> typedef long long Time;
>
> class Timer {
> private:
> Time start_time;
> Time& total_time;
> }
>
> Timer::Timer(Time& tot) : start_time(gettimeofday()), total_time(tot)
> {
> }
>
> Timer::~Timer()
> {
> end_time = gettimeofday();
> total_time += end_time - start_time;
> }
>
> So I wanted to extend the
>
> CancellableTimer : public Timer
> {
> private:
> bool canceled;
>
> public:
> // if I call obj.cancel() then the destructor should
> // not
> void cancel(void) { canceled = true;}
> }
>
> Now, it seems to me that I can't get the derived class behaviour without
> modifying the base class, because the base destructor always runs.
>
> But it also seems that by Liskov Substitution Principle, a
> CancellableTimer IS A Timer, so it'd be nice if I could extend Timer in
> this way.
>
> What am I missing?

Ignoring all the discussion of LSP this and quibble that, you've already worked out that the destructor in the base class runs regardless. What you're missing is that subclasses generally restrict behaviour, they don't extend it. (That's an exaggeration, but it holds in this case.) Your base class should be CancellableTimer; and if you want a Timer that can't be accidentally cancelled (which you reasonably might), make a subclass that hides the cancellation mechanism. Virtual functions will help.

Tim Rentsch

unread,
Jul 24, 2017, 1:17:55 PM7/24/17
to
Mr Flibble <flibbleREM...@i42.co.uk> writes:

> On 22/06/2017 14:52, Tim Rentsch wrote:
>
>> Another way of expressing the second point is not being able to
>> distinguish types and classes. It's been known for more than 30
>> years that types and classes are not synonymous, but that
>> understanding hasn't yet percolated out to the community at
>> large. Unfortunately C++ is firmly wedded to the concept of
>> seeing classes as types (or sometimes the other way around)
>> rather than supporting the two as distinct notions. Given how
>> C++ has evolved it would be very difficult to change that now,
>> but I think it's worth starting the conversation, so that at
>> least the understanding will be there even if it takes the
>> language a while to catch up.
>
> What absolutely nonsense! Of course classes are types. An instance of
> a type is an object, thus:
>
> int a = 42; // a is the name of an OBJECT of scalar TYPE 'int'.
> foo o = 42; // o is the name of an OBJECT of class TYPE 'foo'.

First let me clear up a confusion. My earlier comment was made
in a limited context, where the only kind of data structuring
being considered is classes. Of course there are other kinds
of data structuring constructs available, eg, built-in ones like
'int' or 'double', or user-defined ones like enumerations. Let's
use the word "structure" to encompass all of the different sorts
of things that define the layout or memory structure of objects.
So "structure" includes int, double, structs, unions, classes,
pointers, arrays, etc.

Returning to the main point under discussion, what I said is
classes (or more generally, structures) are not /synonymous/ with
types. A class (or other kind of structuring construct) can
stand in for a type, but it is not the same as a type. A type
can be more information than a structure, eg,

int pi; // "plain" int
const int ci;
volatile int vi;

The variables pi, ci, and vi all have the same structure, namely
the same size, alignment, and representation that any 'int'
object has. But they have different types, which means different
rules for how they can be used. For example, it's okay to access
the variable 'ci' as if it were just a plain int, as long as the
access is a read access, not a write access. The variable 'vi'
can be accessed as if it were a const volatile int, but not as
if it were a const int.

A type can be less information than a structure, as can be seen
with array declarations:

extern Animal *zoo[];

Here we know 'zoo' is an array (of pointers to Animal, which need
not concern us further), but we don't know how big the array is.
The type tells us /partial/ information about the structure, but
not complete information.

Some types don't deal with structure at all:

extern void initialize_recovery_system( int threads );

Here of course we have a function type. There is no structure
information associated with a function type.

In C++, reference types seem to fall in a strange kind of limbo.
Of course what we expect is that references will be implemented
by holding on to some kind of pointer, but the C++ Standard
insists that references are not objects (or maybe that they
might no be objects? I'm not sure). If T is a reference
type, then 'new T' doesn't work. But it's okay for a class or
struct to have a member of a reference type, and you can bet
your bottom dollar that how the class/struct is laid out will
have some space allocated for that reference member.

If anyone is interested to look into this further I recommend
this paper, which AFAIK is the earliest explanation for how types
and structures are different. (In Smalltalk the only kind of
structuring construct is classes, but generalizing to other
kinds of structuring mechanisms should be easy to see.)

A type declaration and inference system for Smalltalk (1982)
(http://citeseer.ist.psu.edu/showciting?cid=104638)

Roughly speaking, a "type" is like an interface, and a "structure"
is like an implementation. But don't take that literally, it is
meant just as a way to aid understanding, not as an exact analogy.

Mr Flibble

unread,
Jul 24, 2017, 6:09:59 PM7/24/17
to
On 24/07/2017 18:17, Tim Rentsch wrote:

> A class (or other kind of structuring construct) can
> stand in for a type, but it is not the same as a type.

Again you are wrong. In C++ a class is a type.

/Flibble

David Brown

unread,
Jul 25, 2017, 3:33:31 AM7/25/17
to
You seem to have missed Tim's point entirely.

He has said that types and classes are not /synonymous/ - they are not
the same thing. This is clearly true. There are many kinds of "type"
in C++ that are not classes - "int", "double", pointers, functions,
lambdas, etc.

But you are arguing as though Tim had said "classes are not types" - and
that is /not/ what he said.


I don't think Tim expressed it very well when he said "a class can
/stand in/ for a type" - I think that adds confusion (the rest of his
post was, IMHO, very good). I think it is better to say that a class
(or other structuring construct) is part of what defines a type. Other
parts include qualifiers like "const" and "volatile" - these are also
needed in determining what you can do with an object of that type.

leigh.v....@googlemail.com

unread,
Jul 25, 2017, 7:11:32 AM7/25/17
to
Obviously you can't read. He explicitly stated that a class isn't type which is patently absurd.

/Flibble

David Brown

unread,
Jul 25, 2017, 9:00:45 AM7/25/17
to
On 25/07/17 13:11, leigh.v....@googlemail.com wrote:
> Obviously you can't read. He explicitly stated that a class isn't type which is patently absurd.
>

Instead of snipping everything, please quote from Tim's post /exactly/.
That would make it much easier to see what he did or did not
"explicitly state".

And you might also like to try reading his post yourself, where Tim
tries to explain to you the difference between classes and types.


Jerry Stuckle

unread,
Jul 25, 2017, 10:20:50 AM7/25/17
to
On 7/25/2017 7:11 AM, leigh.v....@googlemail.com wrote:
> Obviously you can't read. He explicitly stated that a class isn't type which is patently absurd.
>
> /Flibble
>
In that statement you are perfectly correct - as David has so repeatedly
demonstrated.

--
==================
Remove the "x" from my email address
Jerry Stuckle
jstu...@attglobal.net
==================

Mr Flibble

unread,
Jul 25, 2017, 12:30:33 PM7/25/17
to
You are missing the point: there is no difference between classes and
types because classes are types.

As far as Tim's waffle about cv qualifiers are concerned: cv
qualification does not create a type from a non-type; cv qualification
changes a type from one type to another.

/Flibble

David Brown

unread,
Jul 25, 2017, 3:27:52 PM7/25/17
to
On 25/07/17 18:30, Mr Flibble wrote:
> On 25/07/2017 14:00, David Brown wrote:
>> On 25/07/17 13:11, leigh.v....@googlemail.com wrote:
>>> Obviously you can't read. He explicitly stated that a class isn't
>>> type which is patently absurd.
>>>
>>
>> Instead of snipping everything, please quote from Tim's post /exactly/.
>> That would make it much easier to see what he did or did not
>> "explicitly state".
>>
>> And you might also like to try reading his post yourself, where Tim
>> tries to explain to you the difference between classes and types.
>
> You are missing the point: there is no difference between classes and
> types because classes are types.
>

Are all types classes? If not, then there /is/ a difference. Even if
you disagree with everything else Tim (or I) wrote, surely you can agree
that there are types which are not classes. Thus if nothing else,
classes and types are different in the way that Toyotas and cars are
different.

> As far as Tim's waffle about cv qualifiers are concerned: cv
> qualification does not create a type from a non-type; cv qualification
> changes a type from one type to another.
>

I'll let Tim reply to that, if he wants to.

Mr Flibble

unread,
Jul 25, 2017, 4:19:02 PM7/25/17
to
On 25/07/2017 20:27, David Brown wrote:
> On 25/07/17 18:30, Mr Flibble wrote:
>> On 25/07/2017 14:00, David Brown wrote:
>>> On 25/07/17 13:11, leigh.v....@googlemail.com wrote:
>>>> Obviously you can't read. He explicitly stated that a class isn't
>>>> type which is patently absurd.
>>>>
>>>
>>> Instead of snipping everything, please quote from Tim's post /exactly/.
>>> That would make it much easier to see what he did or did not
>>> "explicitly state".
>>>
>>> And you might also like to try reading his post yourself, where Tim
>>> tries to explain to you the difference between classes and types.
>>
>> You are missing the point: there is no difference between classes and
>> types because classes are types.
>>
>
> Are all types classes? If not, then there /is/ a difference. Even if
> you disagree with everything else Tim (or I) wrote, surely you can agree
> that there are types which are not classes. Thus if nothing else,
> classes and types are different in the way that Toyotas and cars are
> different.

What utter codswallop. I have no idea why you are making the absurd
leap from me asserting that classes are types to me asserting that all
types are classes.

A class is a type of type just as a pointer is a type of type or a
built-in scalar is type of type.

/Flibble

David Brown

unread,
Jul 25, 2017, 4:44:10 PM7/25/17
to
"There is no difference between classes and types" - does that ring a bell?

Tim wrote "A class ... is not the same as a type", and you replied
"Again you are wrong".


I don't actually think you think all types are classes in C++. But
that's what you wrote, in your haste and desperation to yell at people
for being wrong rather than actually reading, thinking, and constructing
a useful argument.

Mr Flibble

unread,
Jul 25, 2017, 4:48:48 PM7/25/17
to
Tim also wrote "A class (or other kind of structuring construct) can
stand in for a type, but it is not the same as a type." which is
erroneous: a class is a type.

/Flibble

David Brown

unread,
Jul 25, 2017, 5:06:02 PM7/25/17
to
I agree that - at least in the context of C++ - classes are kinds of
types. That's what the standards say. They don't give all the
information you might need about a type - cv qualifiers can be added.

In a wider context, it can perhaps make sense to distinguish between
"type" and the structure of the data and its methods, as Tim said - I am
not convinced one way or the other.

My reason for posting is your knee-jerk "you are wrong" replies to an
interesting post covering a range of issues.

Tim Rentsch

unread,
Jul 28, 2017, 1:17:04 AM7/28/17
to
I'm sorry we weren't able to have a more productive
conversation.
0 new messages