Home > C++, C++11, C++14 > Easier To Use, And More Expressive

Easier To Use, And More Expressive

One of the goals for each evolutionary increment in C++ is to decrease the probability of an average programmer from making mistakes by supplanting “old style” features/idioms with new, easier to use, and more expressive alternatives. The following code sample attempts to show an example of this evolution from C++98/03 to C++11 to C++14.

VecVecClear

In C++98/03, there were two ways of clearing out the set of inner vectors in the vector-of-vectors-of-doubles data structure encapsulated by MyClass. One could use a plain ole for-loop or the std::for_each() STL algorithm coupled with a remotely defined function object (ClearVecFunctor). I suspect that with the exception of clever language lawyers, blue collar programmers (like me) used the simple for-loop option because of its reduced verbosity and compactness of expression.

With the arrival of C++11 on the scene, two more options became available to programmers: the range-for loop, and the std::for_each() algorithm combined with an inline-defined lambda function. The range-for loop eliminated the chance of  “off-by-one” errors and the lambda function eliminated the inconvenience of having to write a remotely located functor class.

The ratification of the C++14 standard brought yet another convenient option to the table: the polymorphic lambda. By using auto in the lambda argument list, the programmer is relieved of the obligation to explicitly write out the full type name of the argument.

This example is just one of many evolutionary improvements incorporated into the language. Hopefully, C++17 will introduce many more.

Note: The code compiles with no warnings under gcc 4.9.2. However, as you can see in the image from the bug placed on line 41, the Eclipse CDT indexer has not caught up yet with the C++14 specification. Because auto is used in place of the explicit type name in the lambda argument list, the indexer cannot resolve the std::vector::clear() member function.

8/26/15 Update – As a result of reader code reviews provided in the comments section of this post, I’ve updated the code as follows:

innervec

8/29/15 Update – A Fix to the Line 27 begin-begin bug:

innervec

Categories: C++, C++11, C++14 Tags: , ,
  1. fisherro
    August 23, 2015 at 12:03 am

    With C++03 you could use std::for_each with std::mem_fun_ref(&std::vector::clear). I tend to think that’s better than all the others except the C++11 one that uses range-based for. Although this sort of “functional” approach can get hard to read for anything more complex. A separate functor, a lambda, or ranged-based for can quickly become a better choice.

    Ranged-based for is great except when you want to iterate over less than the full range. I really wish C++11 had included some adaptor classes to help make ranged-based for more flexible.

  2. Kamil
    August 23, 2015 at 5:50 am

    Surely since the lambdas only operate on its argument, there is no need for reference capture ?

  3. Lorenzo Gatti
    August 24, 2015 at 3:39 am

    C++ 11 option A has the tersest and most readable loop header (no unneeded std::begin and std::end) and loop body (no repeated types, no syntactic “noise” from lambda functions). When would the other new variations be useful?

    • August 24, 2015 at 5:37 am

      For the reasons you state, I prefer C++11 option A over all others too. Perhaps people/orgs who strive to minimize loops in their code prefer the for_each() options.

    • fisherro
      August 27, 2015 at 12:10 pm

      I find the main cases where I don’t use ranged-based for—as hinted at in my previous comment—are when I don’t want to iterate over the entire range. There are tricks to doing that with ranged-based for. e.g. A simple Range class that takes two iterators and has begin & end member functions. But since they aren’t standard, such an idiom is less likely to be immediately recognized by the reader.

      • August 27, 2015 at 12:14 pm

        I can tell you’re a good programmer. You care about the future maintainers more than being clever. 🙂

  4. gm
    August 24, 2015 at 5:37 am

    The loops in all their versions are needless here –
    _vecvecDouble.clear()
    destructs all elements of the vector, in this case – the vectors.

    • August 24, 2015 at 6:06 am

      It’s an academic example 🙂

      • fisherro
        August 27, 2015 at 12:15 pm

        I do understand that it is an academic example, but I think it would be a much better example if you called the function something like “clear_inner_vectors” and didn’t clear the outer vector in the function.

        My fear is that a novice seeing this example would mistakenly assume that _vecVecDouble.clear() would not destruct the inner vectors, and then write code based on that mistaken assumption.

      • August 27, 2015 at 12:22 pm

        Great point I’ll fix it soon. Of course, since it’s posted as a .png and not inline text, as many people have pointed out, it takes longer 🙂

  5. August 27, 2015 at 12:00 pm

    C++98/03 didn’t have std::begin and std::end as free functions. You had to use the std::vector::begin and end versions.

    • August 27, 2015 at 12:02 pm

      Ah yes. I noticed that mistake a few days ago and was wondering when someone was going to point it out. Good catch!

  6. Ted
    August 28, 2015 at 11:59 am

    Good example!!

    The 8/26/15 Updated Code’s line 27:
    Second argument should be vecVecdouble.end( )

    Can I reproduce this article to Traditional Chinese ?

    • August 28, 2015 at 12:26 pm

      Damn! Nice catch Ted. I’ll have to update it one more time now 🙂

      You can reproduce it in any language you’d like. I’d be flattered if you did.

  1. No trackbacks yet.

Leave a Reply

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 )

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: