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.
Dear Mr. Plauger,
Just a quick note, because I often have thoughts on various articles, but if I tried to catch up on my procrastinations, this would be a very long letter. So I'll try to keep it short on my first attempt :) But it can't be so short as to not at least say good mag, keep it up. Anyhow, here we go...
Say we have class Vector, which is a random access interator over class Scalar. The "canonical" example would be
typedef double Scalar; // i.e. Vector is array of Scalars typedef Scalar *Vector;but, in general, Vector is a class that overrides [], ++, *, etc. So, given v is a Vector
Vector v = ...;then *v is a Scalar (a double), v++ is a Vector still, and v[3] is a Scalar.
But &v[3] is a *Scalar not a Vector. That is, &v[3] is not necessarily a Vector (except in the "canonical" case).
So things like:
Vector v = &vect1[startindex]; Vector w = &vect2[startindex]; while(...) v++ = w++;etc, etc. (or whatever) just don't work.
What can be done about this? We cannot override the &x[] operator! And the Scalar class shouldn't know anything about Vectors, so is the only advice "Doctor my arm hurts when I do this..."?
Just wondering.
Sincerely,
Tony Van Eerd
Image North Technologies
tony@inorth.comBasically, yes. Templates in STL are designed to be used in certain stylized ways. If you stray from the approved idioms, you get in trouble. So the answer is, "Don't do that." pjp
Editor,
CUJ had been changing its look, but evolution turned to avalanche when Miller Freeman, Inc. became publisher. I just received my March 1996 issue and it is ablaze with color, shaded boxes, even little icons. A layout designer could now joke that CUJ has some bleeding edges.
Having said that, I actually find most changes pleasing (except the icons... I hate icons). I wrote though to say, please stop while you are ahead. I have seen too many magazines transform into an illegible mess. Don't make me search for the editorial amongst the ads.
I buy a magazine for content and legibility. If I wanted something shallow but flashy, I could instead read various stunning but brain-dead magazines, watch those television shows that are designed for eight-year olds and adults who think the same, or surf many web sites that say little but take three minutes per page to download over a dial-up.
People and their eyes have not changed over the last 300 or so years. Unlike the Web or even television, newspapers and magazines have had the experience and confirmation of history for what makes effective and legible layouts. The big change since, say, 1750 is that reading is now for the masses rather than for the select few. But those masses have never heard nor want to know of C/C++. Let them have their MTV. For CUJ, keep up the great editorial and informative ads in the clear and easy-to-read format.
Andy Levinson
andyl@netcom.comAdvice noted. pjp
Dear Mr. Plauger,
I just ordered The C/C++ Users Journal CD-ROM. This was an excellent idea! You may wish to consider implementing a CD-ROM subscription program with yearly updates, perhaps with an annual cost around $15, beyond the initial $50 for the 5.5 year archive.
When I decided to learn the C/C++ language a year or so ago, a friend recommended subscribing to your publication. That was the best educational investment I ever made (and it continues to be). Your (evolving) new format is wonderful, your articles get easier to read and more spiffy with each passing month. My only wish is that you could pack more information into each issue (more Q&A would be a great start). The STL is a godsend, and your coverage of it makes it very accessible. I hope to see more examples of its use in the months to come. Other topics I am interested in (that should be read as "have trouble with") are the strategies and tactics behind the use of the new RTTI features, dynamic type casting, exceptions, and namespaces. The essential motivations are easy to grasp, but writing good code with these features seems to be an uphill struggle.
I eagerly await the next issue....
Regards,
Charlie Lusignan
Graduate Student in Physics
University of RochesterAlso noted, thanks. pjp
P J Plauger,
After reading a little about the <utility> header (in the March 1996 CUJ), I can safely say that C++ has reached that mystical threshold that many languages have suffered from in the past, the design-by-committee add-the-kitchen-sink threshold.
C++ has become the PL/1 of the Nineties.
There was a day, a day not so long ago, that a competent programmer could comprehend the entire language at hand, such as Pascal or C. ISO/ANSI X3J11 did such a wonderful job at unifying and standardizing C, it was almost poetic. And then it seemed like such a natural thing to add to this wonderful language, bringing it from the structured programming paradigm of the 1970s into the object-oriented paradigm of the 1990s.
Alas, what seemed like an elegant idea has resulted in a bloated mostrosity. Does X3J16 really expect mere mortals to remember even half of the language or the library? I'm not the first to notice this, but when you can't tell what a simple statement like c = a + b; means without hours of digging into class declarations, overloaded operators, implicit and explicit type conversions, template rules, etc., then it's safe to say that it's too much, that it's gone too far.
Don't misunderstand; I like object-oriented programming. I've been using O-O techniques since the 1980s, before they called it O-O. Making C O-O would be wonderful. But C++ isn't truly object-oriented, and one reason is because it's got too much (non-O-O) C left in it.
Why isn't ::main() a constructor of the program's root class? Why aren't member functions always virtual? Why do we need both the dot and -> operators? Why define private inline member functions in header files, in plain view of everyone? Why have header files at all? Perhaps ANSI could have learned a few simple lessons from better languages like Simula, Smalltalk, and Eiffel.
Unfortunately, I as a programmer must educate myself on C++ if I want to stay in the game. I must learn about all the obscure nooks and crannies of the language, because who knows when I'll have to decipher some hotshot programmer's ramblings on exception handlers that invoke overloaded operators within a nested multiply-inherited virtually derived template class in its own namespace.
At least PL/I had implementation subsets.
David R. Tribble
dtribble@onramp.net
drt@wcwcen.wf.com
Dear Dr. Plauger,
Recently, I've been reading More Effective C++ by Scott Meyers (another excellent book by an excellent author). While it is very informative and useful it confirms several conclusions that I reached several years ago and I would like your take on it.
Specifically, C++ suffers from too much complexity. Don't get me wrong, I love the language and I enjoy developing applications in it. However, I don't think it deserves its place as the most popular O-O language. If you don't know exactly what you are doing, there is far too much rope to hang your project on. And, it takes longer to develop an application in it than it does in "higher"-level languages.
My conclusion is that the language should only be used by experts in those situations that demand the full power of the language. Most corporations would be better served by using Smalltalk, Eiffel, Delphi, etc. to develop the majority of their applications in (I have a prejudice in favor of O-O languages).
That also means that C++ will decline in popularity over the next decade (assuming more people come to view it as I do) and that another (presumably O-O) language will take the fore.
From where you sit, what is your opinion about both the state and the future of the language?
Sincerely,
Randy AstleI think that building C++ atop C has proved to be both its strength and its weakness. It would not be so widely used if it weren't so easy to mix with a widely successful language. It would be more object oriented if it didn't have to retain so much backward compatibility. Whatever you think is the "right" way to program, it pays to notice what lots of programmers choose to do. Then find a subset of that popular language that you can live with. pjp
Editor,
In regards to "The Poor Man's Serial Protocol Analyzer" (CUJ, February '96), the information about select is not relevant to BSD-based systems... (it may be relevant to only AIX, which seems to be less UNIX than Linux). I've used a number of UNIX systems, I've never seen select defined to return values packed into a long.
I also feel the phrase "older device" drivers should be rephrased to "incorrect device drivers." select calls have been supported for a long time. The below is copylefted, you can freely publish it.
From the gnu libc documentation on select:
"A better solution is to use the select function. This blocks the program until input or output is ready on a specified set of file descriptors, or until a timer expires, whichever comes first. This facility is declared in the header file sys/types.h.
int select (int NFDS, fd_set * READ-FDS, fd_set *WRITE-FDS, fd_set *EXCEPT-FDS, struct timeval *TIMEOUT)The select function blocks the calling process until there is activity on any of the specified sets of file descriptors, or until the timeout period has expired.
The file descriptors specified by the READ-FDS argument are checked to see if they are ready for reading (or if a server socket, for accepting a connection); the WRITE-FDS file descriptors are checked to see if they are ready for writing; and the EXCEPT-FDS file descriptors are checked for exceptional conditions. You can pass a null pointer for any of these arguments if you are not interested in checking for that kind of condition. "Exceptional conditions" does not mean errors errors are reported immediately when an erroneous system call is executed, and do not constitute a state of the descriptor. Rather, they include conditions such as the presence of an urgent message on a socket. (See *Note Sockets::, for information on urgent messages.)
The select function checks only the first NFDS file descriptors. The usual thing is to pass FD_SETSIZE as the value of this argument.
The TIMEOUT specifies the maximum time to wait. If you pass a null pointer for this argument, it means to block indefinitely until one of the file descriptors is ready. Otherwise, you should provide the time in struct timeval format; see *Note High-Resolution Calendar::. Specify zero as the time (a struct timeval containing all zeros) if you want to find out which descriptors are ready without waiting if none are ready.
The normal return value from select is the total number of ready file descriptors in all of the sets. Each of the argument sets is overwritten with information about the descriptors that are ready for the corresponding operation. Thus, to see if a particular descriptor DESC has input, use FD_ISSET (DESC, READ-FDS) after select returns.
Marty Leisner
<leisner@sdsp.mc.xerox.com>Thanks for the information. pjp
Dear Mr. Plauger,
In the last letter in the "We Have Mail" section of the February 1996 issue, you respond to Robert Shaver that "a comment can indeed be placed anywhere whitespace is permitted in C or C++." This is only true if the comment is a C style comment, i.e., /*...*/, not true if it is a C++ style comment, //...
i = j /* comment */; // ok i = j // comment ; // error! void foo( int bar /* comment */ ); // ok void foo( int bar // comment ); // error!Shaver "assumes that `comment' is already defined" so maybe he did mean C style.
Just another reminder to never get rid of the mail section. It is one of the most informative pieces of CUJ. Keep it up!
Jose Fernandez
Seer Technologies, Inc.
josef@mailgate.seer.comThanks for the clarification. pjp
Editor,
On page 10, example 3 of your March 1996 column, you write:
3) Hoist all the names, as in:
#include <cstdio> using namespace std; int main() {std::printf("hello world\n"); return (0); }
One would figure that example 3 is identical to example 1, with the exception of the using line. So either there's a typo, or using is doing something I'm not familiar with.Walt Stoneburner
<wls@wherry.com>
ps. Which is it?It's a typo. The whole idea is to eliminate the need for all those namespace qualifiers. pjp
Editor,
I am just having a terrible time getting my strings to print out properlywhen I develop for DOS computers (Windows seems so easy). I can't seemto get the following to work:
printf(stdprn, STRING);where STRING is the text that I am outputting to the printer. If I use either _bios_printer, or bdos call, I get print but the line that I am sending to the printer never justifies correctly, even though I am using a \n to begin a new line. What happens is that the printer moves to the next line but begins to print the next line at the end of the first line like this:
Notice Of Disciplinary Action This form...Here is what my code looks like:
void do_print(char *line){ while(*line) dbos(0x5,*line++,0); }or
void do_print(char line[85]){ register int t; for(t=0;t<strlen(line);++t) _bios_printer(_PRINTER_WRITE,line,0); }Both of the above functions are called like this:
do_print("Notice Of Disciplinary Action\n");Help!
Mark A. Malo
PC Specialist
Northside Mental Health Center
mark@northsidemhc.orgLooks to me like this form of printing does not convert the internal newline character on output. If you write to stdout or stderr, the newline gets changed to a carriage return/line feed as needed to begin a new line properly. A line feed alone (which is what \n becomes outside the program) just advances the line, as you report. The quick fix is to end each line with \r\n instead. pjp