Journal Articles
Browse in : |
All
> Journals
> CVu
> 115
(21)
|
Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xt and user-summary-[publicationtype].xt. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles . The templates will get the extension .xt there.
Title: Questions & Answers
Author: Administrator
Date: 06 August 1999 13:15:32 +01:00 or Fri, 06 August 1999 13:15:32 +01:00
Summary:
Body:
It would help with this column if those of you who either answer questions that others ask you or have your questions asked could take the time to write up the question and the answer. If you want your name can be with-held. This column is about real questions and real answers.
From: Peter Hudson <PeterH@wagm.com>
Dear Francis,
As a man who knows many things, I wondered if I might ply you with my latest problem.
I have benefited no end from your suggestion that Leen Ammeraals' book on STL would be a good place to start STL. Since ploughing through this tome I have tackled others.
One facet of all these books is however consistent:
None spend any time explaining how to use STL with user defined types. They all stick to ints, chars, doubles and the like. I can find only a short piece in Lippman on specialisation (which may or may not be the technique I need to use). Even Bjarne does not refer to it.
Are you aware of any books on this subject? Or am I just looking at this the wrong way? Or am I just crying for the moon? Or do I have the wrong end of the stick entirely?
I think there are two parts to this question, the first is 'how should the STL be used with user defined types?' and the second is 'Are there any good books covering this?'
My choice of book after mastering Ammeraal's STL for C++ programmers is Generic Programming and the STL by Matt Austern.
That is my answer to the second question, so how about the first one?
I think the answer to that is simple as well. As long as you ensure that your UDT is what I call a value type you can use it almost exactly like a built-in type. The only caveat is that some STL algorithms (e.g. sort) and collections (such as map) when used in their default form require the comparison operators defined for your type. Note that I said by default; you are always at liberty to provide a comparison function explicitly when instantiating the template.
Now let me back track and summarise what I mean by a value type. By a value type I mean any type that has strict public copy semantics. That means that the user has not made either the copy constructor or the copy assignment operator private or protected. Furthermore, either there are publicly defined versions with strict copy semantics (unlike auto_ptr, for example, where the copy process changes the object being copied), or it is possible for the compiler to generate suitable functions (i.e. no const qualified data members and no reference data members).
The single largest cause of error in using the STL is applying it to object or polymorphic types (and a common and serious design error is making polymorphic types publicly copyable and/or copy assignable). The STL is designed to work with values. If you want collections of objects use 'handles', pointers or smart pointers that can be safely provided with strict copy semantics.
From John Skelton <John_Skelton@compuserve.com>
In the answer you give in June's EXE, you say that:
uppercase(hello).data
is exactly equivalent to:
(&uppercase(hello))->data
Please can you point me to a reference to confirm that? I've the ANSI X3.159-1989 standard, and also K&R (1st & 2nd Eds) and Harbison & Steele (2nd Ed) but I've been unable to convince myself that you're right. Actually, I think you're wrong as the nearest ref I could find was about (&E)->MOS but that's not phrased in a way that would support what you say...
In case you've only a ref. in the ISO std, I hope it's as like the ANSI std as I've seen it said. <g>
The C9X draft (or whatever it is) explicitly says the C you used is allowed, but it doesn't make sense that you were referring to C9X so I'm ignoring that.
I think there are a number of very subtle issues floating around here. But let me start with the simple one. Consider:
struct X { char data[10] }; typedef X X; // make X a typename even in C int main(){ X item; ... }
Now I hope we all agree that (until we introduce C++ operator overloading for & and ->) item.data and (&item)->data are required to be equivalent. I think (hope) that that is simple and clear.
Now the next question is to consider the case when the struct X object is an unnamed return value from a function. Presumably uppercase(hello).data means apply the dot operator to the returned value. So the next question is to what is the address operator being applied in (&uppercase(hello)), the function or the returned value. A quick check of precedence reveals that the function operator has higher precedence so the & must be applied to the result of evaluating uppercase(hello). In addition the unary & can only be applied to a function designator or to an lvalue so (&uppercase(hello)) is ill-formed. Now the question is whether uppercase(hello).data is also ill-formed (which is what I was originally contending). Let me rephrase that, are you allowed to apply the dot operator to an rvalue? The answer to that question is 'yes' by deduction from the standard (in 6.3.2.3 it states that 'The value is that of the named member, and is an lvalue if the first expression is an lvalue').
So it seems that John is indeed correct (which surprised me because it breaks what I had always regarded as a required equivalence). However I think we still have a problem. According to this uppercase(hello).data must be an rvalue of type char[10]. But C does not support array rvalues because there is nothing to decay to a pointer (rvalues do not have location).
The original context was whether printf("%s", uppercase(hello).data); was well-formed. I think the answer is no, not because you cannot pass structs by value - you can - but because you cannot then handle the array data when you try to extract it from the cocoon of its encapsulating struct.
I would welcome opinions from other language lawyers.
Notes:
More fields may be available via dynamicdata ..