HDTenEightyP/NetNews huggingface dataset:
From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: Zero-length structures and pointer comparisons
Organization: Computer Science, University of Melbourne, Australia
Date: Mon, 21 Dec 1992 12:02:43 GMT

maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:

>However, lets consider that Unix file names are 'pointers' to files,
>and that links are allowed.
>
>Then the average program cant tell if two file names point to
>the same file or not, since computing the inode number is the only
>way to do that, and only super users can do this calculation.
>(Imagine I'm right even if this isnt the case. Is it the case?)

No. Computing the inode number is not a privileged operation.

>Would this make such a system 'unworkable'?

Not if the system had mandatory (as opposed to advisory) locks.

>The issue is whether pointers must provide any more functionality
>than the ability to access an object, that is, whether object
>identity can be established by pointer comparisons.

Like it or not (in many ways I don't!), it seems that this principle
is firmly entrenched in C++. Consider the requirement 
empty classes must have non-zero sizes, etc.

>I suggest that whole classes of software can be written that 
>do not rely on the ability to test if two pointers refer
>to the same object or not, other types of software require
>this information.
>
>Perhaps we can conceive two types of pointers, type 1 
>provides no comparisons at all, type 2 allows equality test.
>
>Most of the code I've written uses type 1, and most uses
>of type 2 could be rewritten as type 1.

Equality tests are often needed in assignment operators, to
check for the special case of x=x.

>In those cases where type 2 pointers are desirable, it
>seems reasonable to restrict them to pointers
>to objects created directly by me, and not the operating
>system.
>
>Thus I would like to see the ARM == rewritten so the
>results of == on externally derived or otherwise mangled
>pointers are implementation defined.

As I said in a previous post, I think that this is already
the case for C, and I expect it to be the same for C++
when the ANSI or ISO C++ standard finally comes out.
Once you have invoked the operating system, all bets are off.

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
From: chased@rbbb.Eng.Sun.COM (David Chase)
Newsgroups: comp.std.c++
Subject: Re: C++ already *has* nested functions SO WHAT'S THE BEEF?
Date: 22 Dec 1992 00:49:22 GMT
Organization: Sun
NNTP-Posting-Host: rbbb
Keywords: nested functions, dumb ideas

rfg@netcom.com (Ronald F. Guilmette) writes:
>So what is it that people are complaining about?

>	o	[fake] nested functions ... cannot access `auto' and
>		`register' *objects* declared within a containing local
>		scope.  

>I believe that it is this last item that concerns people the most.

This is true.  The rest is all largely syntatic fluff.  Fluff is nice,
but that is not what people are asking for here.

> ... when I hear about
>all of these complicated schemes for supporting dynamic "up-level addressing"

It was easy.  We did it for Modula-3, two different ways.

>and also such things as "special" kinds of function pointers for holding
>pointers to nested function

This is not necessary at all.  See previous post for details on how to
avoid special function pointer representations for nested functions.

>(and a special new syntax for declaring such things) 

Not necessary.

>Haven't the implementors already got enough to do??  

Yes, we do.  On the other hand, if you look at in terms of costs and
benefits, especially in comparision to the rest of the language, this
is a relative win.  If you look at it in terms of percentage of total
work, this is also not a big deal.

>Can't people figure out how to simply pass any needed `auto' variables
>which are local to the containing function as additional actual
>argument to the nested (called) function on those very rare occasions
>when this is actually necessary??  I mean what the devil is the
>problem here?

You're not getting the picture here.  If I declare (to choose a common
and perhaps over-simple example) a bag-object with an iterator
interface that takes a function-to-be-applied-to-each as a parameter,
then it just takes a function, period.  It doesn't matter if it needs
0, 1, 2, or many pointers to auto variables passed to it.  This
simplifies the interface, and has the advantage of not adding clutter
(e.g., explicit state variables to be passed in and out of the
function) where it is not needed.

>I mean c'mon folks... This endless "featurism" has got to stop somewhere!

I agree, but I think we mean different things.  C++ has many features
that I still haven't figured out how to use, or even if they are in
fact useful.  It has many of other features that I put in the "plenty
of rope" category (be careful not to wrap it round your neck).  Nested
functions, I know how to use, and I know how they can be used to
simplify interfaces, and they are not especially "dangerous".

David Chase
Sun
Newsgroups: comp.std.c++
From: pkt@lpi.liant.com (Scott Turner)
Subject: Re: pointer comparisons
Organization: Liant Software Corporation
Date: Sun, 27 Dec 1992 05:01:18 GMT

In article <9236102.3238@mulga.cs.mu.OZ.AU> (Fergus James HENDERSON) writes:
> One of the most important principles of C was that if you didn't use a
> feature, you shouldn't have to pay for it. This principle was carried
> through to C++. On the topic "Design Notes", Bjarne Stroustrup wrote
> 	"Features that would incur run-time or memory overheads even when
> 	not use were avoided" [C++PL, 2nd Ed. pg 3].
> 
> As a feature, padding empty base classes fits this description exactly.

"Padding empty base classes" is not the feature -- it's the
simplest implementation.  The desired feature is:
    Two pointers to the same type, which point to distinct objects
    of that type, compare not equal.

> It has a very significant memory overhead, especially if there
> are multiple levels of derivation involved. 

A smart implemetation would typically have no overhead.  The most practical
example which has come up is Jamshid Afshar's, which incurs no overhead
even with existing implementations.  The example which requires padding
(originally Johan Bengtsson's) is contrived.

> In the case of deriving from empty structures, it is absolutely TRIVIAL
> to insert padding yourself *IF* you really need the addresses to be different.

This is getting away from my point, but how do you know a compiler will 
provide storage space for unused padding within a struct/class?

> Furthermore, if the programmer didn't
> ask for the padding and didn't want it, how could you say it was
> anything other than "uncalled for"?

There's a good chance the programmer needs data or object code compatibility 
with other code.  The other code may use the above-described feature.
--
Prescott K. Turner, Jr.
Liant Software Corp. (developers of LPI languages)
959 Concord St., Framingham, MA 01701 USA    (508) 872-8700
UUCP: uunet!lpi!pkt                          Internet: pkt@lpi.liant.com
Newsgroups: comp.std.c++
From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: Zero-length structures and pointer comparisons
Organization: Computer Science, University of Melbourne, Australia
Date: Mon, 21 Dec 1992 11:01:23 GMT

jbn@lulea.trab.se (Johan Bengtsson) writes:

>Markku Sakkinen (sakkinen@jyu.fi) wrote:
>: BTW, actually total order is
>: a simple thing within an OODB _because_ the identity of each object
>: is assured not to change.
>
>It would impose severe restrictions on how the virtual address space
>could be used though.  The OODBMS may end up in a situation where
>it can't get a persistent object into memory, not because it has used up
>all virtual memory addresses, but because all unused virtual memory
>adresses would violate the total ordering property.

I thought that the idea was that for OODBMSs, you DON'T compare virtual
addresses for pointers to persistent objects, instead you compare the object
ids. Maybe someone could explain the problems in a little more detail?

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
Newsgroups: comp.std.c++
From: bill@twwells.com (T. William Wells)
Newsgroups: comp.std.c++,comp.std.c
Subject: Re: Question about sizeof in C/C++.
Date: 1 Jan 93 13:54:52 GMT
Organization: None, Mt. Laurel, NJ

In article <jamesc.725854759@bart> jamesc@swapsdev.state.state.COM.AU (James Cribb) writes:
: jimad@microsoft.com (Jim Adcock) writes:
: >jamesc@swapsdev.state.state.COM.AU (James Cribb) writes:
: >| Given
: >|     struct Something*  ps;
: >|     unsigned  k;
: >| do the C or C++ standards guarantee that
: >|     &ps[k] == ((char*) ps) + k * sizeof(struct Something)
: >
: >No.  The relationship holds only if ... k is less than or equal
: >to the number of elements in the array pointed-to by ps
:
: My code meets those conditions, but just out of interest,
: if k is too big, what could cause an inequality (of the addresses)?

In the compiler I've written, if an object is known to be less
than 64K bytes, its index arithmetic is done with 16 bits but all
pointer arithmetic is done with 32 bits. So, if sizeof(*ps) * k
is over 64K, the pointer arithmetic will create a different
result from the index arithmetic.

(Well OK, for this particular example, the compiler is actually
smart enough to see the equivalence between the index expression
and the pointer addition and so the equality would hold. But if
the (char*)ps weren't detectable as an object pointer, they
wouldn't be equal.)

---
Bill                            { rutgers | decwrl | telesci }!twwells!bill
bill@twwells.com
Newsgroups: comp.std.c++
From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: pointer comparisons
Organization: Computer Science, University of Melbourne, Australia
Date: Sat, 2 Jan 1993 13:35:25 GMT

maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:

>pkt@lpi.liant.com (Scott Turner) writes:
>>	Does it govern base class subobjects?  As I understand it,
>>	base class subobjects are objects, and hence are covered.
>
>	One consequence: abstract objects can exist.
>
>	Corollary: such objects have states not accessible via
>	the contiguous storage allocated for them.
>	(via virtual function calls)

As I noted in a previous article, I don't agree with Scott Turners belief
that base class subobjects are objects. To me, these are absurd 
consequences, and thus I conclude that the assumption used in deriving them
must be flawed.

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
Newsgroups: comp.std.c++
From: jimad@microsoft.com (Jim Adcock)
Subject: Re: Zero-length structures and pointer comparisons
Date: 24 Dec 92 00:45:34 GMT
Organization: Microsoft Corporation

In article <1992Dec18.204337.3084@lth.se> dag@bellman.control.lth.se (Dag Bruck) writes:
|In <comp.std.c++> maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
|>
|>In fact, p==q iff objects equal is unimplementable on some machines.
|>That is, even the existing ARM requirement is unworkable.
|
|No, some machines are unworkable :-).

Agreed -- we just disagree on what machines.  The implementors of Smalltalk, 
Smalltalk machines, the Mac systems, The Windows systems, OODBMSs, and I,  
believe that machines with immovable objects, paging in 4K chunks, 
are "unworkable" for serious object oriented work.  The basic problem is 
that objects are typically about 100 bytes, implying an average of 40 
objects per 4K page.  The 40 objects do not typically consistently remain 
to the same temporal working set.  Thus paging needs finer granulaty, 
or objects must be moveable.  Objects cannot in general be moveable to
an appropriate current temporal working set and simultaneously retain their
global address space orderings in memory.  Unless one had hardware paging
in much smaller chunks than 4K -- which in fact 386/486 machines DO support
in one addressing mode -- not commonly used in typical OS's.

Newsgroups: comp.std.c++
From: pkt@lpi.liant.com (Scott Turner)
Subject: Re: Pointer comparisons
Organization: Liant Software Corporation
Date: Mon, 21 Dec 1992 18:18:08 GMT

In article <1gt9qjINNsrr@darkstar.UCSC.EDU>, daniel@cse.ucsc.edu (Daniel R. Edelson) writes:
> There's also a problem regarding inline functions.
> Specifically, under common file-based C++ implementations, 
> the address of an inline function  can vary between
> compilation units. Thus, the requirement from
> Ansi C (Sec 3.3.9)
> 	``If two pointers to function types ... both point to
> 	the same function, they compare equal.''
> is false under common C++ implementations.

An inline function (such as you speak of) has internal linkage.
Its definition is in the header file, so internal linkage implies
that there is a different function in each compilation unit.
The requirement from standard C is honored.
--
Prescott K. Turner, Jr.
Liant Software Corp. (developers of LPI languages)
959 Concord St., Framingham, MA 01701 USA    (508) 872-8700
UUCP: uunet!lpi!pkt                          Internet: pkt@lpi.liant.com

Newsgroups: comp.std.c++
From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: Pointer comparisons
Organization: Computer Science, University of Melbourne, Australia
Date: Fri, 25 Dec 1992 14:14:30 GMT

larsn@Autodesk.COM (Lars Nyman) writes:

[...]
>Thus, I cannot even trust that a '!=' test will return 1 for two objects
>that are not the same !

That is the only possible interpretation of the ARM (as it currently
stands).

>This must surely be wrong... can somebody, please, correct me and explain
>what I'm overlooking.

The definition of objects being "the same" is not clear.

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
Newsgroups: comp.std.c++
From: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Subject: Re: Argument matching
Organization: MAXTAL P/L C/- University Computing Centre, Sydney
Date: Fri, 1 Jan 1993 16:18:13 GMT

In article <1992Dec31.170854.21696@lpi.liant.com> pkt@lpi.liant.com (Scott Turner) writes:
>In article <1992Dec31.053242.3376@ucc.su.OZ.AU>, maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>> Proposal: 
>> 
>> 1) for the purposes of computing the signature of a function,
>> the symbols 'const', 'volatile' and any trailing '&' are ignored.
>
>> 2) As usually, attempting to define two functions with the same
>> signature results in a duplicate defintion.
>
>The worst effect of this idea would be that
>
>	void f(int&)
>and	void f(const int&)
>
>could not be overloaded.  This is useful and I don't think bad design.

	However, it *is* the intention of the proposal as it stands.
Similarly,

	f(int*);
	f(const int*);

would not both be allowed. The argument in favour of this
is that overloading is for two purposes:

A)	families of semantically equivalent operations on different types
	e.g. sin(float), sin(complex)

B)	convenience for accidental overloading
	e.g. draw(gun); draw(picture)
	or   sin(float); sin(priest);

In case (A) overloading is desirable because the associated
'transparency' renders the program more readable and amenable
to change of the types (float->complex). 

Addition of extra overloaded functions may cause re-binding,
say sin(double) is added, but it doesnt really matter
because this doesnt affect the overall semantics.
(Just precision and efficiency in this case)

In case (B) it is hoped the context will supply sufficient
context so that the reader does not imagine that the sin of
a priest is mathematical.

In the case that two functions

	f(int&);
	f(const int&);

are desired, their use in a program would be extremely sensitive
to the exact nature of the actual arguments, and the consequences
dramatically different. I would argue it is better style to have
two functions with different names:

	func_f(const int&); // proper function
	proc_f(int&);  // procedure--warning side effects!

and the loss of overloading is in fact desirable.
In particular, if a program had the function:

	f(const int&);

and the function

	f(int&);

were added, the meaning of the program would change: the call

	f(i);

may suddenly allow 'i' to be modified yielding unexpected results.

The prinicpal disadvantage of disallowing overloading on int& and 
const int& is I think restricted to their use in operators,
since these are not conveniently renamed.

For named functions, why is transparency of semantically distinct
functions desirable?

I also remain confused about

	f(const volatile int&);
	f(volatile int&);

-- 
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
	Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Newsgroups: comp.std.c++
From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: Zero-length structures and pointer comparisons
Organization: Computer Science, University of Melbourne, Australia
Date: Mon, 21 Dec 1992 12:15:39 GMT

maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:

>kanze@us-es.sel.de (James Kanze) writes:
>>As it should.  The ARM (and the upcoming ANSI standard) can only
>>address what happens in the context of C++, not what happens to the
>>pointer once the OS gets its hands on it.
>
>	No, this is not true IMHO. The ARM can and does explicitly
>or implicitly say "implementation defined" where it means that.
>When the ARM says "so and so will be the case" then it must
>always be the case.

No. The ARM described a contract between implementations and programmers,
such that IF the programmer abides by certain restrictions, then
the program will produce certain behaviour. If the programmer does
not abide by these restrictions, then the ARM does not guarantee anything
about the behaviour of the program.

>>In the same way, I would understand the ARM to be saying that all
>>pointers generated by a correct program to point to any object defined
>>(including a dynamic definition by new) in C++ will compare equal.  If
>>you give the pointer to the OS, and it gives it back to you, then any
>>guarantees must be made by the OS, and not the C++ language.
>
>	I agree. But that is not the case. The ARM says different.
>It absolutely requires pointers to the same object to compare
>equal, without qualification. The system MUST ensure this
>to classify as conforming.

This statement is NOT without qualification. Virtually the whole of the
ARM is qualified by the caveat that if the program invokes undefined
behaviour, then all bets are off. Since the ARM is a reference manual,
not a standard, this caveat is implicit rather than explicit.

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
From: jamshid@ut-emx.uucp (Jamshid Afshar)
Newsgroups: comp.std.c++
Subject: Re: Must derived class reserve space for an empty base class?
Summary: don't now, but I still have shopping to do
Date: 23 Dec 92 06:27:30 GMT
Organization: The University of Texas at Austin; Austin, Texas

In article <5450@holden.lulea.trab.se> jbn@lulea.trab.se (Johan Bengtsson) writes:
>Jim Adcock (jimad@microsoft.com) wrote:
>: On the contrary, requiring unnecessary and unexpected padding within
>: structures just to meet your new requirements would be extremely 
>: undesirable, in my opinion.
>
>But the cases where "unnecessary" padding would be required would
>have very minor impact on the majority of programs, at least if I
>may consider the current implementation of virtuals (vtbl).  After all,
>inheriting from a truly empty base class (no virtuals) is quite uncommon,
>don't you think?

The fact the following idiom works under all current C++
implementations, and that it will probably continue to work no matter
what ANSI says, is what most worries me and why I originally posted
this question.  Programmers will continue to do things like
	class Register {
	   Set<Register*> alive;
	protected:
	   Register() { alive += this; }
	   virtual ~Register() { alive -= this; }
	   static void foo();  // do something to all registered objects
	};

If a special-case rule is not added making the above safe on *any* C++
implementation, I hope more C++ literature will point out the fact
that the above idiom is incorrect.  I've been doing stuff like this
for years and never gave it a second thought.  I guess the correct way
to do this would be to always add a dummy char to empty base classes,
but then that's a waste on existing implementations.  Besides, if we
are all going to do this, then why not instead make the compiler do it
-- it could do a much better job of determining when padding is
necessary.

>If pointer distinctness (as defined above) allows useful semantic constructs,
>such as the very common idiom for operator=:
>"if ( &other == this ) return", then a small and rare storage overhead
>in examples such as the one below could easily be tolerated (IMHO).

I hadn't thought about this situation.  I'm sure there are many other
cases besides operator=() where a member function wants to know if
'this' compares equal to the address of a parameter.  Yes, I know
there are many cases when the address of two distinct objects compare
equal when cast to |void*|, but as far as I know this is the only
situtation where the address of two distinct objects compare equal
without the aid of an eye-catching cast.

I'm still not sure how I feel about this situation.  I'm going to take
a closer look at my code after the holidays to see how often I
erroneously assume that when two EmptyAbstractClass*'s compare equal
they are both pointing to the same object.

Jamshid Afshar
jamshid@emx.utexas.edu
Newsgroups: comp.std.c++