[openbeos] Re: Coding Suggestion -- Templates, Iterators

  • From: "Bill Beebe" <wbeebe@xxxxxxxxxx>
  • To: <openbeos@xxxxxxxxxxxxx>
  • Date: Sat, 27 Oct 2001 16:51:26 -0700

> I came across the following code today (actually its from CppTest):
>
> void TestSuite::run (TestResult *result)
> {
>     for (std::vector<Test *>::iterator it = m_tests.begin ();
>             it != m_tests.end ();
>             ++it) {
> // loop code
>     }
> }

Here's mine.

// This should be in the TestSuite header file.
//
typedef std::vector<Test *>
    TestVecPtr;
typedef TestVecPtr::const_iterator
    TestVecIter;

// This should be in the class definition.
//
TestVecPtr
    m_tests;

// Iterate through a collection of Test base objects, performing
// the test on each item. Return the agregate test result when done
// via TestResult.

void TestSuite::run(TestResult &test_result)
{
    TestVecIter
        tv_iter,
        tv_end(m_tests.end());

    for(tv_iter = m_tests.begin(); tv_iter != tv_end; ++tv_iter)
    {
       // loop code, setting test_result to some value.
    }
}

> In this example, I would do:
>
> typedef std::vector<Test *>::iterator TestIterator;

Agreed. I would also typedef the iterators for this std::vector. See above.

> Another thing is that iterators are pretty common, so I think having a
> standard macro for traversing with one would be very useful. Here's my
> suggestion:
>
> #define foreach(elem,set) for (elem = set.begin (); elem != set.end ();
> ++elem)
>
> Oh, I know, I can hear the groaning out there... "we don't use #define
> macros -- that's old-style, icky C crap that we sophisticated C++
> programmers don't use". Maybe, but I still think macros are extremely
> useful when used sparingly and judiciously. They're awfully good at
> hiding uglies.

The reason that #defines are not used is that they introduce non-type-save 
constants that C++ can
not catch when improperly used. Defines also (as in this case) introduce class 
functions and
stand-alone functions that can be better implemented using standard function 
notation. A classic
case in point are the definitions of min() and max() where in one case they're 
#defined and unsafe
and the other they're implemented via templates. If your code is so ugly that 
it needs to hide
behind a #define, then maybe the code should be re-written. To finish the 
argument, there is already
a for_each() function implemented. It takes three arguments; the container 
start, the container end,
and a function to execute on behalf of each element in the container.

> Now using those two code snippets above, I can rewrite the example
> (using OpenTracker formatting) as follows:
>
> void
> TestSuite::run (TestResult *result)
> {
> TestIterator i;
> foreach (i, m_tests) {
> // loop code
> }
> }

The problem with that example is the programmer's desire to use one-letter 
variables. Using
one-letter variables looks great in a text on programming but are the bane of 
software maintenance.
Go looking for one-letter variables (at 3 am in the morning before a large code 
drop/demo after 14
hours of debugging an intermitent bug) in a large body of code, especially if 
you use any of the
vowels.

Other points:

1 / Use const where ever possible, such as const arguments or const iterators.
2 / Pass by const rather than pointer, and if you must pass by pointer, pass by 
const pointer or
pointer to const ref.
3 / Keep lines as short as possible. Don't run on. Since people have been 
writing they've been
writing in a format with allows multiple columns on a page. It's because it's 
easier for humans to
read. You can't have multiple columns in source code (not yet, anyway),  but 
you can have
readability. For example, in declairing variables:

void MyFunc(const std::string &str)
{
    std::string
        work_str,
        str_token,
        another_str;
    int
        count,
        foo,
        bar
   ...
}

3 / Use indentation and whitespace to promote readability. Python lives by 
this. So should all other
languages.
4 / For the sake of those you work with please use a little verbosity in your 
coding.
5 / For the sake of those you work with please use comments, especially a block 
at the start of each
class function or function. We'd like to know what you're trying to do, 
especially if we've never
seen the code before. This goes hand-in-hand with point 4 above.
6 / Use namespaces. Use the ones that already exist (such as std) and create 
new ones to avoid
collisions in new code.

If I sound overly critical, I'm not. I'm in violent agreement with your goals. 
You're moving in the
right direction, and it's a lot better than quite a bit of open-source (and 
closed-source) code I've
seen.

Also, please look at 
http://www.camtp.uni-mb.si/books/Thinking-in-C++/Contents.html, as it covers
C++ with lots of examples.



Other related posts: