Departments


We Have Mail

Letters to the editor may be sent via email to cujed@mfi.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. Briand,

I am writing you because of your remark, "Have other readers noticed this involuntary [ink] transfer?" in CUJ February 1996 (reponse to a letter from William Garces).

It reminded me of the same problem I had (many years ago, long before I subscribed to CUJ and WDJ) with Dr. Dobb's Journal. Many of the earlier magazines have my fingerprints (in white) on the cover. Since then, I developed the habit of never holding a magazine in my hands for longer than, say, a minute. When I read it, I put it on a table or in my lap.

Just for a test, I glossed through the magazine for about 15 minutes, while holding it in my hand, and yes, the ink does let loose (although the problem appears to be less severe than the DDJs I mentioned).

In your defense, I should add that I suspect that my hands are "aggressive." At the technical school where I worked with metal cutting machines, I learned that some people cannot touch a freshly cut steel component without seeing their hand prints in rust within a few hours. Others can. Teachers told me that it was because some people have more acid sweat than others.

Thiadmer

I confess to getting sweaty palms when reading certain magazines, but seldom CUJ. — pjp


Dear PJ,

In a recent installment of Q&A, Peter Becker helped a reader who wanted to print an amount of money in BC++. Here's a suggestion for making Pete's solution more elegant. We can write a new manipulator:


ostream& _money(ostream&os, long amount)
    {
    char buf[20];
    // Pete's code here
    os << buf;
    return os;
    }

inline OMANIP<long> money(long amount)
    {
    return OMANIP<long> (_money, amount);
    }

The exact form of OMANIP may differ between compilers, and can sometimes be a macro. However, it allows us to write expressions like:

cout << "end-user price: " ;<< money(400)
     << "dealer price: " << money(300);

Jean-Louis Leroy

Yup. Manipulators often provide more readable notation. Thanks. — pjp


Dear Sir,

People trying to make initial contact with the Association of C & C++ Users via our published internet address of info@accu.org have been having their e-mail bounced. This has nothing to do with the health of ACCU. Demon Internet Services are contracted to redirect mail to accu.org. At least twice during the last six weeks they have lost the vital MX record that provides such redirection. Obviously we have no way of contacting those who had email bounced.

If any of your readers wish to obtain information about ACCU and have email to info@accu.org bounced they can send e-mail to me at my private address of francis@robinton.demon.co.uk. Anyone else interested in C, C++, Java and related programming languages can get more information either by e-mail or by writing to me at 64 Southfield Road, Oxford, OX4 1PA. It may interest overseas readers to note that we have members in 26 countries.

Francis Glassborow
Chair of ACCU

Dear Editor,

I found a serious flaw in the code published with "Debugging with Exceptions," in the October 95 edition of CUJ. The author overlooked the fact that the type of an object being thrown is static: the compiler doesn't do any dynamic cast to find out if a handler matches the current exception. As a result, only CATCH_ALL clauses work correctly with those redefinitions.

I apologize for any trouble that this bug might have caused, and I submitted a fix containing macro redefinitions that work better.

Best Regards,

Alessandro Vesely

[We provide the file redefafx.h on this month's code disk mb]


Dear Sir:

I just recently discovered CUJ and enjoy your editorials especially. They reflect my thoughts; I thought I was alone. I miss the days when we were intimate with the innards of the computer and knew where every byte was. We peeked and poked, entered video RAM, made our own characters, etc. At that time I felt I was in control of the machine; now I don't and am fighting desperately to regain control.

I was programming when there was no language. I used Fortran on a 1401. I had a $100 Timex, which could do things no PC will do now and forced me to write programs less than 2 KB. I had a Toshiba T-100 (not T-1000), which was pre-DOS with no software, and for which I had to write my own word processor in BASIC (that I still use and can improve or modify to suit various projects). Three years ago I got the "latest thing," with Windows and every kind of software pre-loaded that I could ever want. I enjoy playing computer games with it but miss my favorite computer game: programming.

So now I am learning C++. I like your magazine because it takes me into the innards. I also respect accurate grammar, spelling, and punctuation; these are excellent in your magazine, as in other programming publications, probably because it is imperative in programming.

Sincerely,

Bruce L. Harding

We do make a real effort to keep both the technical content and the linguistic expression reasonably accurate. Glad you noticed. — pjp


Hello!

I'd like to correct what I believe is an error in your column. In "Standard C/C++," March 1996, p 16, col 3, par 3, you mention the relation between paper, rock, and scissors as a partial ordering function. I am afraid this function is total: all the elements in your set may be compared. It is not an ordering function, because it lacks a fundamental property: it is not transitive.

An example of a partial ordering function is the strict comparison of the absolute value of signed integers: 1 and -1 are different elements which you cannot compare between each other.

What gets in the way with the utility template functions is thus the ability to redefine operator< for other purposes than for ordering. In a way, one can conversely see this as a way in which C++ enforces on it statically part of the ordering semantics. Nice isn't it?

Best Regards!

Marc Girod
Nokia Telecommunications

You're quite right, the example was inappropriate. Thanks for pointing out the error. — pjp


Dear Mr. Plauger:

I would be interested in your comments on the effects of using operator overloading in C++. I recently converted some engineering software from C to use operator overloading as implemented in the header <COMPLEX.H>. Mostly the complex multiply, divide, add, and subtract operators are used to solve matrices in the program. There are many calls to these functions. My original C code used functions I wrote myself, e.g. complex_div(a, b) to do the complex operations.

I found using operators slows the program considerably. Using Watcom C++ Version 10.5, a calculation that took 20 seconds to do with my own complex functions now took 34 seconds. Borland C 3.1 with my complex functions took 25 seconds for the same calculation and with operator overloading 40 seconds. Borland C 4.5 took slightly longer at 26 seconds for user written functions and 49 seconds with operator overloading. All the tests were done with the same compiler switches set in both cases. The program code (size of the .EXE file) is also larger when operator oveloading is used.

I talked to an experienced programmer and he said there should be no execution time penalty in using operator overloading unless the overloaded operators are virtual functions, in which case the program must scan a list to find the appropriate one to use and this could take time. Looking at the header <COMPLEX.H>, they don't seem to be virtual functions.

I wrote a small program to test the two methods. I found that if compiled to assembler, each function call with the user functions involves only one call in the assembler code, but when operator overloading is done, there are two calls in the assembler code, requiring more pushing and popping of registers as well as the two function calls, so this may be the reason for the slower execution.

I would really like to use operator overloading as it is much easier to read the code. I guess I can live with the larger .EXE size as memory is less of a problem with 32-bit DOS extenders and windows. However, I fear that the advantages of higher levels of C (i.e., C++) may be offset by fatter and slower code. The speed is really important to me as some simulation calculations I have done, have taken 49 hours on a Pentium 90! A few hours saved can be important as a calculation may be possible overnight rather than having to wait for a weekend.

Until someone can show me where I am going wrong, I have converted back to my user-written complex functions.

Sincerely,

Ian B.K. Simpson, P.Eng.
North Vancouver, B.C.
103245.2061@compuserve.com

I can't thing of a good reason why overloaded operators should be uniformly worse than explicit function calls, but that second function call is evidence enough that this is the case with your code. Is some sort of implicit type conversion responsible for that second call? In any event, you're doing the right thing if performance is so important. Measure, then pick the fastest approach. — pjp


Dear Mr. Plauger,

I have been following your articles on the STL with great interest. This has been a marvelous series.

I have a question, however, on the template distance discussed in the April C/C++ Users Journal. The article states that this template computes, essentially, n = last - first. However, looking at the templates, it would appear to be more accurate to state that the template computes n += last - first.

If I am not mistaken (which is certainly possible), if the caller does not zero n before calling distance, the computed difference will be added to the current value of n. If I am correct, then I suspect this is going to trip up a lot of programmers trying to use these templates.

Earl Bennett
ebennett@rust.net

You are correct, or at least you were. Since I wrote that column, the definition of distance has changed. It now returns the value last - first, at least in principle. You can only implement the new version of distance with a compiler that supports partial specializations, of which there are none to my knowledge. In my implementation of STL, I retained the older form under the name _Distance, with the behavior you correctly describe. — pjp


Dear CUJ,

The article on "Selectable Default Constructor Arguments," by Glen Deen (CUJ, February, 1996) presented a soloution to a problem I have run into several times. Unfortunately his technique has a severe drawback. In some cases, especially if the class encapsulates a system resource, it makes no sense to modify members after the constructor was called. This is nasty because especially window classes tend to have awful parameter lists.

The improved solution sketched in Listing 1 therefore uses a special class to pass parameters. I didn't like the idea of overloading operator() and use set functions named by a macro instead.

Sincerely,

Joachim Zobel

There's certainly more than one way to skin this particular cat. — pjp


Editor,

I am a big believer in marking reference and pointer arguments to a function as const wherever possible. However, I have run into a problem that I have been unable to solve. Given the example code below:

class example {
    char *my_stuff;
public:
    example(void);
    ~example();

    operator const char *(void);
};

example::operator const char *(void)
{
    return my_stuff;
}

void test(example const &x)
{
    const char *value = x;
    // should invoke operator
    // const char *
    puts(value);
}

The assignment on the first line of test will cause an error because

example::operator const char *()

is not a const member function. Now, by inspection we can see it really is const in the sense that it does not modify the object to which it is being applied nor does it allow anyone else to modify the object. However, the compiler hasn't been told this. The problem is, where do I put the const to mark the function as a const member function. Using MetaWare's High C++ compiler for the '86 family, I get the following results:

For

const operator const char *(void)

I get the diagnostic,

"cannot specify return type
"const int" for operator function."

And

operator const char * const (void)

compiles, but functions are not marked as const member functions.

I've checked in the ARM to no avail (this subject does not seem to be covered). Any ideas?

Sincerely,

David D. Hagood
Software Engineer
IFR Systems, Inc.
Wichita, KS

The proper place to put the const qualifier is after the parameter list, as in:


 operator const char *(void) const;

Think of these trailing qualifiers as decorating the implied this pointer parameter. — pjp


Editor,

Any chance we could get Marco Savard to wrap these interfaces into a C++ class design? (See "Shared Memories as Files," CUJ, April, 1996.) All of my UNIX programming these days is in C++.

By the way, you pleasantly surprised and tickled me when you published that letter I wrote to your column in the April issue. I realize that stacks and op amps have very little in common dynamically, of course; however, the point I was alluding to was that formal standard template specifications should drive multi-platform standardization through vendor competitiveness. This should make the STL a common programming tool in the future instead of an empty promise. Ada offered the possibility of a standard generic (i.e., like a template) library in the last decade but vendors were not compelled to provide a "standard generic library" simply because there was no such specification accompanying the language standard. This is where C++ can go a lot further than Ada did in making software reuse more of a reality in the practical sense.

Sincerely (and I'm off my soapbox this time!),

Bryan McKinley
BMC Software, Inc.

I think you'll find that STL will become a true standard for generic programming. It sure does a lot of things right. — pjp


Dr. Plauger,

After 15 years of writing in C I have reached the point where most of my functions contain one or more goto statements. Their purpose is to allow me to avoid having multiple return statements.

I find that allowing multiple exit points from a function adds significant complexity during testing and debugging. I avoid these costs by using goto statements to break out of conditions and move immediately to the function's single block of exit processing logic.

Obviously there are other ways to skin this cat. I have used various combinations of sub-functions and/or status flags to accomplish the same end. Doing so, however, clutters a function with calls and variables that are not directly related to the algorithm at hand.

A disciplined use of goto statements to a single label allows my team to write functions that avoid multiple exit points without extraneous entities. New team members have sometimes been skeptical of this approach, but I have noticed that the idiom becomes more common in their code over time.

Jack P. Starrantino
jpps@voicenet.com jps@semcor.com

With emphasis on the word "disciplined," I personally have no problem with your approach. — pjp