Omit Needless Words (in C++)

In C++ as in life, some people tend to use more words than they need to. As Strunk and White put it: Omit needless words.

Here’s an example I saw again yesterday in a recent peer-reviewed online magazine article showing how to write some C++ code to solve a particular problem. There’s nothing wrong with the code I’m going to show; but it tries to use a technique to "save typing" while accomplishing the opposite because of being unaware of a clever little C++ feature.

I’ll rearrange the particular code I saw to disguise the example (lots of people do this, and it would be unfair to target one person). The code started something like this:

template<
  typename T1,
  typename T2,
  typename T3,
  template <typename A1, typename A2 >class CreationPolicy,
  template <typename A1, typename A2 >class MemoryPolicy,
  template <typename A1, typename A2 >class SnarkPolicy,
  template <typename A1, typename A2 >class HumptyPolicy,
  typename SomeHelperType,
  typename StillAnotherType>
class MyClass
{

So far, so good; these words are needed for the purpose the author is trying to accomplish (it’s a heavy-duty template with enough type parameters to make Andrei proud).

Next comes the definition of MyClass, and some part of that may want to refer to "my type (this particular MyClass instantiation)." Now, it could spell it out as "MyClass< T1, T2, T3, CreationPolicy, MemoryPolicy, SnarkPolicy, HumptyPolicy, SomeHelperType, StillAnotherType >" — but, yuck, who wants to write all that every time?

In an attempt to avoid that verbosity, the class author next writes a convenience typedef:

  // Typedef — to save typing (?)
  typedef MyClass< T1, T2, T3, CreationPolicy, MemoryPolicy, SnarkPolicy, HumptyPolicy, SomeHelperType, StillAnotherType > ThisClass;

(Some of you may be about to interrupt our program with a "but why would he write that when he can just…" — right, but just wait for it.)

Then the code can go on to name "this particular MyClass instantiation" easily, say to pass "my type" to someone else:

public:
  static bool SomeFunc()
  {
    // instantiate some other template with "my type"
    vector<ThisClass> v;

    // call another static function of "my own type"
ThisClass::OtherFunc();

    … more code …
  }

There are two cases of needless words here.

First, the typedef doesn’t save any writing on the call to "ThisClass::OtherFunc()," because that call doesn’t need any qualification at all. It could simply have been written as "OtherFunc();" since that call is already inside MyClass.

Second, and more to the point, the typedef is completely unnecessary in the first place. Why? Because inside a class template, the simple name of the class template automatically implies "this instantiation" including the full parameter list. That is, in the above example there is no difference between typing

MyClass< T1, T2, T3, CreationPolicy, MemoryPolicy, SnarkPolicy, HumptyPolicy, SomeHelperType, StillAnotherType >

and just typing

MyClass

when inside the template.

So the typedef is completely unnecessary, and the original code:

  // Typedef — to save typing (?)
  typedef MyClass< T1, T2, T3, CreationPolicy, MemoryPolicy, SnarkPolicy, HumptyPolicy, SomeHelperType, StillAnotherType > ThisClass;

public:
  static bool SomeFunc()
  {
    // instantiate some other template with "my type"
    vector<ThisClass> v;

    // call another static function of "my own type"
ThisClass::OtherFunc();

    … more code …
  }

could have been written simply (and a bit more clearly) without any typedef, using just the class template’s name or nothing at all:

public:
  static bool SomeFunc()
  {
    // instantiate some other template with "my type"
    vector<MyClass> v;

    // call another static function of "my own type"
    OtherFunc();

    … more code …
  }

Ironically, the typedef not only didn’t save typing, but actually added a little.

Sometimes less is more. Where possible, use fewer words.

3 thoughts on “Omit Needless Words (in C++)

  1. That is, sadly, not equally true when we want to talk about a templated base class, understandably so because a class could derive (directly or indirectly) multiple times from the same base.

  2. Somewhat humorously, your example is not as concise as it could be either. In particular, A1 and A2 could be omitted from the template template parameters. See section 1.5.1 of _Modern C++ Design_.  
  3.  (no name) wrote: "A1 and A2 could be omitted from the template template parameters"
    Right. I didn’t mention that (and some other things) because I was trying to focus on just the use of the class template name. One thing at a time… :-)

Comments are closed.

In comments, use [code] [/code] for code blocks, and the same with angle brackets for code inside text paragraphs. I appreciate and try to acknowledge feedback on GotW articles; if you're suggesting an improvement for a GotW Solution post, please post under your real name (or include it in the comment text) if you would like to be acknowledged here and when the material is updated and expanded in future Exceptional C++ books.

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s