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 PJP:

I just read Randy Astle's letter in the August 1998 CUJ and your response and would like to make a few clarifying comments. The internal compiler error in Randy's code is due to a known bug in Microsoft VC++ 5.0 that shows up when a string literal is used as a default argument in a parameter list. The easiest workaround is to define a std::string variable prior to the class declaration. His code would then be:

#include <string>
std::string strDflt("");

class AClass
    {
public:
    AClass(int anArg,
        std::string
        aString = strDflt);
    };

void AFunction ()
{
    AClass aClass(7);
}

This bug only happens if no definition of a std::string variable exists prior to the use of std::string as a default argument type. The problem has since been fixed in Visual C++ 6.0.

Regards,

Kerry Loynd
Visual C++ compiler team

Thanks for the information. — pjp


Dear Mr. Editor,

The switch statement is one of a few areas that were not revised when we moved from C to C++. In C, the operand to the switch statement and the case labels should always be integers (or integer convertibles) and we seem to have copied the same limitation to C++ for no reason. For example, If I have the following class:

class CMyString
{
    .....
    .....
    // Copy Constructors:
    CMyString(
        const CMyString& other);
    CMyString(const char* other);

    // Assignment Operator:
    CMyString& operator=
    (const CMyString& other);

    // Equivalence Operator:
    bool operator==
    (const CMyString& other);
    ....
};

the following code does not compile:

int main()
{
    CMyString str1  = "SomeString";
    CMyString str2 =
        "SomeOtherString";
    CMyString str3 = "AnotherString";
    switch(str1)
    {
    case str2 :
        // Do Something ...
        break ;
    case str3 :
        // Do Something else ...
        break ;
    }
    return 0 ;
}

In the above code, logically there is no reason why the case labels cannot be of type CMyString. If I have to make it work, I will have to rewrite it as:

int main()
{
    CMyString str1  = "SomeString";
    CMyString str2 =
        "SomeOtherString";
    CMyString str3 = "AnotherString";
    if (str1 == str2)
        {
        // Do Something ...
        }
    else if (str1 == str3)
        {
        // Do Something else ...
        }
}

The simplicity of the switch statement is quite apparent. Logically, it should be possible to construct a switch-case statement for any two objects that have an equivalence operator (operator==) defined. This operator can then be used to make comparisons by switch statement.

Is it something that the designers of C++ have overlooked or something that they considered but decided not to touch for some reason?

Regards,

Kishore Meduri
Senior Software Developer
Electronic Data Systems Inc.
Atlanta GA

Many things could be "fixed" when overhauling C, not the least of which is the switch statement. The C++ standards committees chose not to try to fix everything, wisely in my opinion. Note that even Java, which is more of a departure from C than C++, retains the switch statement in all its idiosyncratic glory. But you're basically correct — there's no reason why the switch statement could not be generalized along the lines you suggest. — pjp


CUJ,

Perhaps I am taking too liberal an interpretation of the following sentence from your editorial guidelines: "Though we may accept a story on any C or C++ related topic, check first for our immediate story needs." But I thought it might be worth a punt to suggest the following idea for an article in your magazine.

I am a keen Java and C++ developer but it struck me of late that rather than inventing an entirely new language and foisting it on the world at large, the team who conceived of Java would have done far better to have written a C++ virtual machine. This would have greatly saved on the resources that have been expended (wasted perhaps) on the great Java migration that is taking place.

C++ is a far superior, though more complex, programming language than Java, and there are a vast numbers of developers out there skilled over many years in its usage. Although the principles of Java are the same, it seems absolutely idiotic to sacrifice the progress that has been made with C++ because of the hype that surrounds Java and its Internet applicability. The bottom line is that interpreted C++ would have been an all-round better choice for a platform-neutral programming language.

It's not too late by any means. Were an organisation like the Free Software Foundation to develop the C++ virtual machine, the sense of restoring C++ to its former pre-eminent position would be clear. Because of the vast legacy of C++ tools and software that currently exists, ease of integration with such a replacement for Java would be guaranteed. Computer developers and businesses world-wide could then go back to concentrating on more worthwhile ventures than some follow-the-herd-mentality migration to Java.

I won't at this point delve much further into the idea, as, naturally, I would prefer to get some feedback as to its suitability before I labour in vain. I am a developer myself, with oodles of Java and C++ experience. I have written for several publications on various topics including PC World Australia. I can send you samples should you require them.

Please let me know your interest. I would be happy to further outline and detail my research intentions if you are unsure about its feasability.

Thank you.

Liam O'Duibhir

Java as we know it today is the result of many forces, not the least of which was the desire by James Gosling to invent his own little programming language. (It's not so little now, of course, but then neither is Unix.) Java is also simple enough to give a JVM a chance at catching misuse of references, and other practices that can be either stupid or malicious. It's rather harder to do the same for C++. Still, it would be interesting to see what sort of support you can muster for such a project. — pjp


Mr. Briand,

While in college, I was told a third variable was needed to swap two numbers, and like a dolt, I took it as fact. I thought of this the other day while showering and wonder if anybody else has.

The swap routine is unreadable and only slightly faster then the normal method of swapping two numbers, so there is no real reason to use it, but here it is anyway.

// Compiled with Turbo C++ Version 3.0
// One line swap routine for C++
// programmers by Tredd Barton
     
#include "stdio.h"
     
inline void swap(int& x, int& y)
    {
    x ^= y = (x ^= y) ^ y;
    }
     
void main (void)
    {
    int a, b;
    printf("\nEnter integer A to"
        "swap with B: ");
    scanf("%d", &a);
    printf("\nEnter integer B to"
        "swap with A: ");
    scanf("%d", &b);
    printf("\nInteger A = %d\n"
        "Integer B = %d", a, b);
    swap(a, b);
    printf("\nInteger A = %d\n"
        "Integer B = %d\n", a, b);
    }

Tredd Barton
tbarton@voltec-inc.com
Voltec Inc.

That's cute. It reminds me of something I read in The Armchair Universe, by A. K. Dewdney (W. H. Freeman and Company, 1988). He describes an imaginary world of only two dimensions; all living beings and objects are infinitely flat and live within a 2-D infinite plane. The inhabitants of this world wish to build a computer, and in so doing one of the problems they must solve is how to cross an X and a Y logic path without interference. They can't route one line under the other because in their world there is no such thing as "under." They manage to simulate crossed lines with a system of 12 NAND gates. It's extremely cumbersome, but it works.

If Java had macros, we could put your single line of obfuscated code into a swap macro. This would be useful because it is impossible to write a Java swap function with raw integer parameters — Java passes them by value, and there's no way to coax them into pointers. But then, Java has no macros and that's probably a good thing. I'll file your trick under solutions looking for problems. — mb


Hi CUJ,

I have a few comments on Mike Rumore's "A Binary Search Tree with Iterators" (July 1998). There is another way of iterating through binary trees that requires only a single class for in-order, pre-order, and post-order traversals. You define a very simple state machine that tells the iterator what to do when it comes to a node. For simplicity's sake, I will represent the state machine as an array of characters. Each character will be one of the following:

1 = Go left
2 = Visit the node
3 = Go right
4 = Finished

This means that a state machine sequence of "1234" is an in-order traversal (Left, Visit, Right, Finish). While "1324" is a post-order traversal (Left, Right, Visit, Finish).

The stack needs to be modified to store the current "state" of the node (a simple integer will do). The operator++() function will get the state and determine what to do next. In pseudo C++, the function will look something like Figure 1.

With this iterator you can now iterate through all three types of traversals with a single iterator class. You can also iterate with the reverse of the above three traversals: reverse in-order, reverse pre-order, and reverse post-order. They simply visit the right side of the tree then the left side. Just use a different state sequence.

The level-order iterator still requires a separate class because it uses a queue instead of a stack.

Another interesting side note is that if you use a state sequence of: "12234", then you will visit the nodes twice in an in-order traversal.

In answer to a question from Mike Rumore, the implementation of the iterator does not allow for removing or inserting elements. The iterator would become unstable and might result in visiting nodes that have already been visited or worse. The STL has the same restriction on collections. Any attempt to insert or remove an element invalidates all iterators to that collection.

I have also provided source code; I've compiled it on MSVC 5 with Service Pack 3. The code isn't as pretty as I would have liked, but I didn't have a lot of time. It also uses Rogue Wave classes (RWStack and RWCString). But any suitable implementation would work just fine. I've also included a very simple little test case. The key point of the code is the operator++ function.

Thanks,

John
hinke@roguewave.com

Thanks for sharing that with us. Since we're kind of short on space, I can't show the extra code you so graciously provided. It will be available via ftp as files tree.h and main.cpp in the letters zip file. (Readers can find downloading instructions on p. 3.) I will also put your code in our Code Review section on our website (www.cuj.com/forum/). — mb


Dear CUJ,

In the July 1998 issue, mb said: I'd like to hear from someone who can argue the pro-reference side of things.

When I teach Data Structures and C++, we develop a lot of template classes. The specific use for references is, as mentioned by David Tribble in the Letters section, when combined with const as an efficient equivalent for pass by value. When using pass by value, the copy constructor gets called. For non-trivial data types this can be overwhelmingly significant. The time spent doing the copying can easily outweigh the time spent doing useful computing. The constant reference technique avoids this problem very nicely, without the user of the function having to worry about it at all.

I don't recommend the use of references for any other purpose though, for the reasons already mentioned by other writers.

Bill Rausch
Software Development, Unix, Mac, Windows
Numerical Applications, Inc.
bill@numerical.com


Hi,

My 5 cents pro references. Consider the callee:

void foo1(theArg& a)
{
   a.value = some_other_value;
}

this much simpler and strightforward than

void foo2(theArg *p)
{
   if (p != 0)
   {
      thaArg& a = *p;
      a.value = some_other_value;
   }
   else
   {
      /* silently ignore? */
   }
}

The second function conveniently aliases the pointed-to value to avoid frequently changing all "."s with "->"s depending on the variable being local or passed as an argument.

I use references for any function, except when managing memory is the issue.

Ciao

Ale

There's no question programmers love a good argument (no pun intended). For the benefit of readers who tuned in late, the argument was whether it was better to use pointers or references as function parameters. The short answer is: it depends.

Last month's letters section contains numerous points for consideration. But this really is the end of it. Thanks to everyone for writing. — mb o