Monthly Archives: October 2014

Effective learning…with Scott Meyers

A few weeks ago, I had the pleasure of being in London. I have always liked London, but was here for an even better reason this time, as I was attending a training course by Scott Meyers on Effective Modern C++ which was based on his forthcoming book!

I attended the course with little to no hands-on experience with the new features of C++11/14. Don’t get me wrong, I’d had a play with a few of the features, but not used any of them in anger. So for the last two days, I was sat in a class room doing some excellent learning.

First things first, Scott is an excellent trainer. He was clear, articulate and had a great way of engaging everyone in, what were at times, very complex topics. He was accessible as well, and ensured that nobody felt like they’d asked a dumb question.

As for the course, some of the material I’d come across before. Scott did a Modern Effective C++ sampler talk at the 2013 Going Native conference, the video can be found here

He also covered topics such as auto and decltype. I’ll confess, before the course, I wasn’t sure what the point of auto and decltype were. It looked like auto was a device to save typing, at least to me initially. So I had a bit of a play with auto during a break just to see it in action. So we’re clear here, this is code I’ve had a play with, so any errors in here are mine, not Scott’s. So with that in mind, let’s consider the following example:

#include <vector>
#include <string>

using namespace std;

// Let's say that this is populated...
vector<string> records; 

vector<string>::iterator rec_it;

for(rec_it = records.begin(); rec_it != records.end(); ++rec_it)
{
	// do something....
}

We want to loop over the vector that’s full of strings which we want to print out what’s in there. But to loop through the vector, there’s quite a bit of setup to do. We have to set up the iterator, and then use it in the for-loop that follows. But how much easier would it be to do this:

// Let's say that this is populated...
vector<string> records; 

for(auto rec_it = records.begin(); rec_it != records.end(); ++rec_it)
{
	// do something....
}

This loops a lot cleaner, and a whole lot simpler. Auto basically deduces what rec_it needs to be. I won’t go in to the detail of how it does this, as I’m still learning that myself at the moment.

An example that Scott did give of the use of auto, was the use of auto within a ranged for loop. Ranged for loops have been in C# and Java for a while now, but it’s good to see that they’ve made their way in to C++. The syntax in C++ is very similar to that in Java and C# too. For example:

for(const auto p&: records)
{
    …
}

The compiler will figure out what sort of object is held within the data structure records. A ranged for loop would is useful when you want do something quickly over a data structure such as printing a collection of strings from a vector.

Don’t get me wrong. I’m not going to use auto everywhere I can for the sake of using auto. As I think that would make certain aspects of the code unreadable. For me, if I want to declare an int, then I’ll explicitly declare an int. I don’t want it to be deduced.

Scott mentioned that in C++ 14, auto can also be used as a return type. I’ll confess this makes me nervous. As it can lead to multiple returns within the body of a function, and in my personal opinion makes the code a bit harder to read and understand. However I will have a play and report back on how I find it..

I also got to learn about constexpr, and I must confess that I was cynical. I was seeing the examples that Scott had, but I wondered “Why not use a ‘static const int’ rather than constexpr.” Scott explained that constexpr objects must have values that are calculated during compilation. So for example, if we were to use std::array (from the new standard) we’d have to use a constexpr to set the size of the array, otherwise the code won’t compile.

One of the fun, but somewhat scary, things that I did do however was to type in one of Scott’s code samples into my editor and hit compile. The sample in the course was thus:

class Widget
{
public:
	template<typename T>
	void setName(T&& newName) // URef or Forwarding Reference
	{ name = std::move(newName); }  // compiles but it's wrong!
	...

};

Widget w;
std::string wName(getWidgetName());
w.setname(wName);  // moves wName into w
                   // wname == &quot;&quot; (probably)

And here’s my code:

#include <string>
#include <iostream>

class Widget
{
public:
    template<typename T>
    void setName(T&& newName)
    { name = std::move(newName);}

    std::string getWidgetName(){ return "fred"; }
private:
    std::string name;
};

int main()
{
    Widget w;
    std::string wName(w.getWidgetName());
    std::cout << "Name is now set to " << wName << std::endl;
    // This is due to the string = operator, which converts double to a char
    // which is why we can do this...
    w.setName(34.3);
    std::cout << "After move, wName is now set to " << wName << std::endl;
    return 0;
}

I found that it didn’t behave in the way we expected. I showed this to Scott, it kicked off a search for what was going on. In the end it was discovered that a string has an assignment operator that takes a char, so anything implicitly convertible to a char (including double) can be assigned to a std::string, same can’t be said for the string constructor. This means that when I passed in another object, that I’d created, it would fail as the object couldn’t be converted to a char.

We also covered topics including lambdas, which was cool. I’ve not used them in any code as yet, but where would we use it? One possible use would be to do a sort of custom object, by using the lambda function as the comparator.

We also covered the concurrency API, which I was quite nervous about. I’ve still not done much with threads as of yet. But I have the course notes, so I plan to have a play. The results of which will end up on this blog soon.

If I had to change one thing, it would have been good to see the code examples being compiled and finding out what happens when you try to build it, or execute it. But I can fully understand that it’s only a two day course, and there’s only so much you can do.

If you get the chance to do this course then do it, it’s well worth it. Failing that, get on the Going Native 2013 video trail. Scott’s talk from there is worth listening to as well.

Advertisements