Here is a quick example refactor. I had some key-value pairs, and was using a std::map (I’ve shown the value type as
T
to avoid cluttering this example):std::map< std::string, T> data;
...
data [ key ] = value;
...
for(const auto &entry : data){
std::cout<<"Label:" << entry.first << "\n";
std::cout<< entry.second.something << "\n";
}
You can see I’m already using a C++11-ism, with the range-based for loop, and auto
. That is so much nicer that I’m not even going to show you the old way it would’ve been done.The problem was I didn’t want to iterate through the map in key order, I wanted to iterate through in the order the items was added. My first idea was to switch to using two vectors, one for the keys, one for the values. But parallel data structures are a nasty code smell.
Then I thought of using
std::pair
. And the above code became this:std::vector< std::pair<std::string, T> > data;
...
data.push_back( {key,value} );
...
(as above)
First thing to observe is that even though the data structure is now completely different, my for(){...}
loop is completely the same. This was partly luck: a std::map
iterator has first
and second
elements, and so does a std::pair
. But we also need to give a big thanks to auto
: it saved us having to even think about what the new iterator type is.Did you spot the second C++11-ism? It slipped by so naturally it might not even have registered. Here it is:
{key,value}
In earlier versions of C++ I would have had to write:
data.push_back( std::make_pair(key,value) );
Only 14 keystrokes saved, but those 14 were pure distraction, and won’t be missed.(This refactor is the correct approach in older versions of C++ too, by the way. All C++11 brings to the party is that it is now easier to do.)
Written with StackEdit.