Departments


We Have Mail

Letters to the editor may be sent via email to cujed@rdpub.com, or via the postal service to Letters to the Editor, C/C++ Users Journal, 1601 W. 23rd St., Ste 200, Lawrence, KS 66046-2700.


Editor,

I have the following question with regard to ARM 14.2. It states that a template class parameter can have no further constraints than that the actual parameter be a type. It further states that this is "more flexible." It would seem to me that this is completely incorrect.

Let's assume for a moment that template class parameters could carry optional constraints which state that the parameter only accepts types of a specific class and its derivatives. Let's further assume that templates are discriminated based on signature and not just name. Programmers would then be able to specialize a template with another template, as well as limit the scope of application of templates to certain classes (which Stroustrup does state would be desirable).

Everyone acknowledges that templates have to be able to be specialized for specific classes. Why should one have to specialize all of their derivatives as well when it is likely to be the exact same specialization? Doesn't this break the abstraction when one has to re-state something defined for one's base when not changing it? Furthermore, why should a template that is made specifically to work with one class hierarchy and that one alone be allowed to try to instantiate itself around other types, just to fail with some indecipherable template instantiation error?

I can see some difficulty in coming up with a good syntax for stating such additional constraints, but the statement that the current method is more flexible is not true. Unless I am totally mistaken about this, I sure hope that the language is extended to include it. Otherwise we will all be missing out on some great potential.

David Flynn
Larson-Davis, Inc
flynn@lardav.com

I don't expect any such extensions to be added to the draft C++ Standard at this late date, though I agree that a mechanism such as you describe could be a boon. — pjp


Dear Mr. Plauger,

Being a very long time CUJ reader and having had assistance from you previously on variable argument lists I would like to ask you for some guidance on the following. I have the following code:

double column_delta;
char   title[81];
strcpy(title, "Dia:");
column_delta = -(strlen(title) + 1);

The result from this is different with different compilers: with HighC on extended-DOS and VC++ on NT it is 4294967291.000000. However, on the SUN it is -5 as expected. If I change the code to any of the following I get the correct -5 result on all the above compilers:

column_delta =
    -(strlen(title) + 1.0);
column_delta = strlen(title) + 1;
column_delta = -column_delta;

What would you have expected from the first assignment expression which gives the unusual result? Any assistance/information you could give on this would be very much appreciated.

Thanks and Regards,
Ken Carroll
Managing + Technical Director,
Tecnocad Limited,
Finisklin Ind. Est.,
Sligo, IRELAND.
Tel +353 71 61382
Compuserve: 100031,3421
Email: kcarroll@iol.ie

You have encountered a commonplace surprise regarding unsigned integer arithmetic. Negating an unsigned value yields its two's complement, which is still treated as a positive value. Hence, the negative of a small unsigned value looks like a large unsigned value. In all the cases above that work "right" (giving the result you expect) the negation occurs in the world of signed floating-point arithmetic. I believe the Sun result is non-conforming, however — you're getting the "right" result for the wrong reason. — pjp


Editor,

Thanks for the tip on the MOZOCK.dll which will be a help to me. I have been using html for local documents as long as I have had access to an editor and viewer. It would have been nice to have you mention where it was located. I downloaded it from ftp.netscape.com in the /unsupported/windows directory. It would have saved some time if you had mentioned the directory location.

I am sure that a Unix wizard could have found it faster but I am a Compuserve user. I am playing with Linux however; I may have to dig out my back issures of The C/C++ Users Journal. I tell my wife that the content of my magazines that clog our household become very important when my interests take a new direction.

Looking forward to re-reading many articles now that my perspectives have changed once again.

Have a nice day.
Wes Szumera

I would have given better directions, but I wrote that editorial while on the road and away from the detailed information. Glad you found it anyway. — pjp


Dr. Plauger:

I've been following your series lately in C/C++ Users Journal. It's been a very useful read for me.

While writing a little user verification module for a program I'm developing I discovered a small idiosyncrasy I don't understand. I have two routines, one to load the password file into a collection and another to save it to disk. Minus some overhead, they are as shown in Listing 1.

The IString is an IBM VisualAge string class and the collection is a KeySortedSet. My question centers around the line marked 'doesn't work.' After reading the docs I do, of course, understand why it doesn't. It fails when any of the strings are multi-word sentences. The extractor keys on whitespace between words as well as EOL/EOF. Anyway, there doesn't seem to be any alternative to the operator>> that would read lines. So I rehacked my routine using getline and fixed_buffer and if statements to extract the lines. This all seems rather clunky — is there any definition upcoming for a line extractor or, gulp, did I miss it in the docs?

Tully Steward
Compressor Controls Corporation
71231.1173@compuserve.com or
Tully_Steward%Compressor_Controls@Mcimail.com

The predefined string extractors behave as you have observed. It is easy enough, however, for you to define your own extractor for a class derived from IString to do just what you want. Such an addition looks to be consistent with the general level of sophistication of your program. — pjp


Dear Mr. Plauger,

I would like to thank you for the article "Implementing <string>" in The C/C++ Users Journal" July/August 1995. I would like to know where I can find the source code of the template class basic_string. As you write, "writing string classes is one of the more popular indoor sports among C++ programers." That is true but also so is reading a string class.

Florin Ioan Chertes

What you see is what you get. The thing about templates is that all the source code often resides in the header. I published a fairly recent version of that header with the August installment. You can also check the Project GNU archives. They too are working on a complete implementation of the draft Standard C++ library. — pjp


Dear Mr. Plauger,

In response to the letter of Steve Price (CUJ, October 1995) regarding the lack of inverse hyperbolic trig functions, I offer three source files for double and long double inverse hyperbolic functions ArcSinh, ArcTanh, and ArcCosh, together with derivations of their formulae. [The code and derivations are on this month's code disk. — pjp] I hope this code solves Mr. Price's problem.

The inverse hyperbolic code here is offered as "Bannerware." Use it freely, even in commercial settings, provided the copyright notice is retained. See the copyright notice in the source for full details.

A minor aside on copyright is relevant here. In one of the professional rags I regularly read I saw a reviewer explode over the "All Rights Reserved" on the software in a book/code disk combo package. Anyone dealing with intellectual property should be aware that in certain countries the affixing of a valid copyright notice was, (is?), not sufficient to protect the work. In these countries the additional phrase "All Rights Reserved" was (is?) required to secure any protection under copyright laws, statutes and treaties. Because of this, the use of this phrase has become standard legal boilerplate for copyright notices. In the code supplied here, I retain the copyright but grant free license for copying and distribution provided my copyright notice is retained.

As someone who primarily programs number crunchers in support of my other engineering activities, I ordinarily work in FORTRAN. When FORTRAN fails to suffice, I usually turn to assembler. C is not my primary or secondary language. I hope my coding "style" does not offend anyone.

I have compiled and tested these routines with Microsoft's compilers, using the command line:

cl /AL /Ox /FPi /G2 test.c     \
arc_sinh.c arc_cosh.c arc_tanh.c

[backslash represents continuation]
with C 5.1, C 6.0, C/C++ 7.0 and VC 1.0, a.k.a., C/C++ 8.0, and with Borland 's compilers:

bcc -ml -1 -Ox test.c          \
arc_sinh.c arc_cosh.c arc_tanh.c

or

tcc -ml -1 -O test.c           \
arc_sinh.c arc_cosh.c arc_tanh.c

(Turbo C 2.0, Turbo C/C++ 3.0 and Borland C 4.02). The Turbo C++ 3.0 compiler didn't handle long double properly. I don't know if this was the compiler or my code. Microsoft C 5.1 and Turbo C 2.0 don't do long double. BCC 4.02 and Microsoft 6.0 and later all properly handle the long double as used in this code.

I tested the inverse hyperbolic functions by computing a hyperbolic then undoing it. The result should match the original argument, trivial differences around the precision limit are, of course, understandable. TEST.C is the major testing program.

In his letter Mr. Price did not indicate over what domain and range he needed to evaluate the inverse hyperbolics. I tried to exercise the inverse hyperbolics over a fairly broad domain.

— Rhoads

Thanks for the contribution. — pjp


Dear Mr. Plauger,

I just read your Editor's Forum on making changes to your cover and the layout of CUJ. I would like to suggest that you also look at changing the printing process you use for your magazine. I subscribe to CUJ and to your sister publication Windows Developer's Journal and the ink on the covers of both magazines has a tendency to rub off leaving little white fingerprints on the cover and ink on my hands. It happens just about every month, especially when I spend more than five minutes reading the magazine. I've never seen this happen on any magazines other than yours.

By the way, what happened to the Code Capsules column? It just quietly disappeared a few months back (or maybe I just missed the explanation). It was one of my favorite columns. I'm sure your more experienced readers probably didn't get much out of it, but for a beginner like me it was very useful. Anyway, keep up the good work.

William Garces
wlgarces@uccs.edu

Chuck Allison had to discontinue Code Capsules because of the demands of his day job. (He is now a bishop in the Church of Latter Day Saints.) That's one of the occupational hazards of this business — anybody who can write knowledgeably about C and C++ has numerous demands on his or her time. We miss him too. However, his replacement, Bobby Schmidt, is taking up the slack with his new column, "The Learning C/C++urve." It addresses C/C++ programming issues at much the same level of accessibility as Code Capsules did. You might want to give it a try. — pjp

About that ink problem: that's really odd! We've never heard that complaint before, nor have we experienced the problem ourselves. Have other readers noticed this involuntary transfer? mb


Dear CUJ,

I like the new look and to prove it I just sent in my subscription renewal.

About a new name for Mr. Saks' column, "Stepping up to C++," how about "Stepping in C++." As you might guess from this suggestion, I have mixed emotions about C++. I have been programming in a subset of C++ for the last two years (we have been avoiding features that aren't portable on the platforms we work on) but they keep making the language more and more complex. Where will it end? I guess I'll find out in the pages of CUJ.

In his first column, "The Learning C/C++urve," Mr. Schmidt touched on several of these issues; C/C++ portability behavior characteristics such as undefined, unspecified, implementation-defined, and locale-specific behavior. Java is attempting to deal with these and other issues. I hope he and your other authors will illuminate the pros and cons of Java.

I really appreciate Mr. Saks going back to "first principles" in his column on grammar notation. Over the years I have picked up and used EBNF, mostly learning by reading examples. It is a powerful tool for describing these types of languages.

Mr. Saks mentioned, in the last paragraph of his column, the implicit differences in the EBNF interpretation for lexical and phrase rules. It seems to me that, at the risk of cluttering the presentation of a language syntax, the placement of whitespace could be explicitly indicated. I may be missing something fundamental; remember I've just been learning this by seeing examples.

There are two types of whitespace, required and optional. (I'm not entirely sure if a comment can be placed anywhere whitespace can occur. I hope you'll correct this if I've got it wrong.) What follows assumes that "comment" is already defined.

First let's define white characters:

white-character =
    " " | "\t" | "\n" | "\r" | "\f"

Next, define required whitespace (rw) and optional white space (ow). (I'm keeping these symbols short so they will intrude the least into the rest of the syntax.)

ow =
      { white-character }
    | [comment] .
rw =
      ( white-character
      { white-character } )
    | comment .

Now whereever whitespace must or may appear it can be explicitly indicated. Your delete example would be:

delete-expression =
    ow [ "::" ow ] "delete"
    ow [ "[" ow "]" ow ]
    cast-expression .

or, to reduce the clutter in the phrase rules:

scope-res-op = ow "::" ow .
delete = ow "delete" ow .
open-bracket = ow "[" ow .
close-bracket = ow "]" ow .
delete-expression =
    [ scope-res-op ] delete
    [ open-bracket close-bracket ]
    cast-expression .

To use the "required whitespace" let's define the C int (correct me if I'm wrong, this is just off the top of my head). The list of all possible integer variations is: int, unsigned, unsigned int, long, long int, unsigned long, long unsigned, unsigned long int, long unsigned int, short, short int, unsigned short, short unsigned, unsigned short int, and short unsigned int. Now let's define the lexical rules:

int = ow "int" rw .
unsigned = ow "unsigned" rw.
short = ow "short" rw .
long = ow "long" rw .

and the phrase rules:

short-int =
   ( ( [ unsigned ] short )
 | ( short [ unsigned ] ) ) [ int ] .
long-int =  
   ( ( [ unsigned ] long  )
 | ( long  [ unsigned ] ) ) [ int ] .
any-size-or-sign-int =
   ( [ unsigned ] int )
 | short-int
 | long-int .

By using the rw and ow in the early definitions of all the tokens, the later phrase rules are not cluttered with them and look much the same as the EBNF using the implicit whitespace rules.

I think the distinction between lexical and phrase rules is somewhat arbitrary. Perhaps we could design the syntax in such a way that none of the phrase rules have terminals in them and all the lexical rules do. What do you think?

Thanks for the great job you folks are doing.

Robert Shaver
Austin TX

A comment can indeed be placed anywhere whitespace is permitted in C or C++. And you're right about the arbitrary division between lexical and phrase rules. The same arbitrariness even extends to the division between syntax and semantics, in many cases. — pjp