The Artima Developer Community
Sponsored Link

The C++ Source
Built-in Type Safety?
by Thomas Guest
June 25, 2005

<<  Page 4 of 4

Advertisement

Other Problems

Before we leave this second example, I want to draw attention to some more potential defects—the ones which haven't happened yet.

The first concerns the choice of unsigned values for the width and height data members of the second version of the Rectangle class. It may seem sensible to use unsigned values here for fields which should not become negative but it means we will have to take extra care with our arithmetic. Consider a member function to grow a rectangle:

    /**
     * Grow the linear dimensions of the rectangle.
     *
     * @note Supply a negative value to shrink the rectangle.
     */
    void Rectangle::grow(int pixels)
    {
        // Take care we don't shrink too much!
        width = std::max(width + pixels, 0);
        height = std::max(height + pixels, 0);
    }
Despite the comment, not enough care has been taken. This is the signalUpdate() problem all over again.

The second potential defect concerns the third parameter to textRender(), the boolean which defaults to false:

    textRender(text,
               full_screen, 
               true); // wrap text
The comment here indicates one problem. We need this comment in order to understand what the boolean actually means. An enumerated value would allow the code to express its intent directly. A second problem is to do with the upgrade path we have started on for textRender(): i.e., adding defaultable parameters at the end of the function. This has the somewhat dubious advantage of not requiring existing users of the function to have to change—I have already suggested that some interface changes should not be made backwards compatible. In time, we may end up with a function declaration like this:
    void
    textRender(std::string const & text,
               Rectangle const & region,
               bool wrap = false,
               bool bold = false,
               bool justify = false,
               int first_line_indent = 0);
Here, we are almost inviting clients to call this function with parameters in the wrong order. It would be better to pack the arguments relating to text display into a structure:
    void 
    textRender(std::string const & text,
               Rectangle const & region,
               TextControls const & controls);    
A more radical approach would be to enlist the Boost Parameters library [8], which uses some astonishing metaprogramming techniques to provide C++ with keyword arguments, allowing us to call our new function as follows (for example):
    boostTextRender(text = "Built in Type Safety?",
                    bold = true,
                    region = full_screen);
or, equivalently:
    boostTextRender(region = full_screen,
                    bold = true,
                    text = "Built in Type Safety?");

Conclusions

There may be some programmers who have been careful (or lucky) enough not to have been caught out by these problems. I suspect far more will know what I'm talking about from personal experience.

There are other points of weakness in the C/C++ type system. Enumerated values and booleans get mistaken for integral types all too easily. And what's worse, in a mixed language system, such as the one deployed on the Talk-To-Me, they can change size and alignment when passing from C to C++.

This article has offered a few survival tips already. I would like to conclude by adding a few more. There's nothing here which hasn't been said before, but I think these bear repeating in the light of the preceding.

Build Cleanly at High Warning Level

You don't want those warnings about "truncation, possible loss of data" to get submerged. They need attention. Preferably, build cleanly with more than one compiler. Ideally, have a Lint build target.

(Learn to) Use a Decent Editor

All good code editors have some notion of a source file in a wider context—as part of a project, for example. So when you write code to construct a rectangle you have immediate access to the declaration of the Rectangle's constructor. This makes it harder to submit parameters in the wrong order.

Invest in Unit Tests

I've already mentioned that unit tests can catch problems in even the simplest code. A unit testing regime can also improve the design of your code. To put a unit under test, it needs to be free of dependencies.

The source code presented in this article has been considerably simplified for expositional purposes. I do not think it a coincidence that the actual defective code was buried in the middle of rather more complicated functions.

Use Keyword Casts

I hope by now it is clear that if you really do need to cast between types you should: C++ provides four different keyword cast operators. These allow programmers to write code which indicates clearly what kind of cast is being done, and why.

And Finally

Fixing defects can be fun. It can be strangely satisfying when, after many hours of setting breakpoints, watching variables, poring over log files, you finally expose the broken logic, the flawed arithmetic, the race-condition. (And how often does the fix turn out to be a one-liner, even a single character change?) Unfortunately the fun soon wears off as release dates approach, to be replaced by fear, panic, and the sense of despair which accompanies all hacky workarounds.

This article has focused on some C++ techniques to circumvent a couple of simple defects. Our best protection, is, however, language independent. It's down to the way in which we approach software development: and that will have to remain the subject of another article.

Acknowledgements

I would like to thank the editorial team at The C++ Source for their help with this article.

References

  1. CheckedInt: A policy-based range-checked integer, Hubert Matthews, http://www.oxyware.com/Publications.html.
  2. The Embedded C++ Specification, http://www.caravan.net/ec2plus/language.html
  3. C++ FAQ, The Named Parameter Idiom, http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.18
  4. Whole Value, Ward Cunningham, http://c2.com/ppr/checks.html
  5. Design Experiences in C++ - Generative Programming Goes Live!, Mark Radford, http://www.twonine.co.uk/documents.html
  6. STLSoft, , http://stlsoft.org/
  7. "True Typedefs", Matthew Wilson, Imperfect C++, Chapter 18, http://www.imperfectcplusplus.com/
  8. The Boost Parameters Library , http://boost.org/ (As of June 2005, this library does not form part of the Boost 1.32.0 release, but can be downloaded directly from the CVS repository.)

Talk Back!

Discuss this article in the Articles Forum topic, Built-in Type Safety?.

About the Author

Thomas Guest is an enthusiastic and experienced computer programmer. During the past 20 years he has played a part in all stages of the software development lifecycle—and indeed of the product development lifecycle. He's still not sure how to get it right. His website can be found at: http://homepage.ntlworld.com/thomas.guest

<<  Page 4 of 4


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us