At the beginning of my Overview of C++11, I show a simple program to compute the most common words in a set of input files. I write the program once using "old" C++ (i.e., standard C++98/03), then again using features from C++11.
In 2009, when I first published the C++11 program (at that time, what became C++11 was still known as C++0x), there was no compiler that could come anywhere near compiling it. Testing the code required replacing standard C++11 library components with similar components available in TR1 or from Boost or Just Software Solutions, and language features like auto, range-based for loops, lambda expressions, and template aliases had to be replaced with typically clumsier C++98/03 constructs that were more or less equivalent in meaning.
This week I tested my simple C++11 sample program with Stephan T. Lavavej's excellent distribution of gcc 4.7 for Windows as well as Microsoft's VC11 beta. gcc 4.7 has lots of support for C++11, but the concurrency API still seems to be largely missing, at least for Windows, so my sample program doesn't get very far with that compiler. [Update 6 April 2012: As noted in the comments below, when invoked in the proper manner on the proper platform, gcc 4.7 compiles and runs my program without modification!]
The situation with the VC11 beta is a lot better. Only two lines have to be changed. The template alias
using WordCountMapType = std::unordered_map<std::string, std::size_t>;
needs to be replaced by its typedef equivalent: typedef std::unordered_map<std::string, std::size_t> WordCountMapType;
And the z length specifier in this call to printf, std::printf(" %-10s%10zu\n", (*it)->first.c_str(), (*it)->second);
needs to be replaced with its VC++ equivalent, I: std::printf(" %-10s%10Iu\n", (*it)->first.c_str(), (*it)->second);
Other than that, the demonstration program I wrote three years ago (which, in fairness to compiler writers, was two and a half years before the C++11 standard was ratified) compiles cleanly with VC11.If you have access to a compiler that compiles my program without modification, please let me know! The program itself is below. You can see a more colorful version of it, along with some commentary, and an example invocation and the corresponding output, on slides 13-15 of the free sample of my C++11 training materials.
Scott
#include <cstdio>
#include <iostream>
#include <iterator>
#include <string>
#include <fstream>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <future>
using WordCountMapType = std::unordered_map<std::string, std::size_t>;
WordCountMapType wordsInFile(const char * const fileName) // for each word
{ // in file, return
std::ifstream file(fileName); // # of
WordCountMapType wordCounts; // occurrences
for (std::string word; file >> word; ) {
++wordCounts[word];
}
return wordCounts;
}
template<typename MapIt> // print n most
void showCommonWords(MapIt begin, MapIt end, const std::size_t n) // common words
{ // in [begin, end)
// typedef std::vector<MapIt> TempContainerType;
// typedef typename TempContainerType::iterator IterType;
std::vector<MapIt> wordIters;
wordIters.reserve(std::distance(begin, end));
for (auto i = begin; i != end; ++i) wordIters.push_back(i);
auto sortedRangeEnd = wordIters.begin() + n;
std::partial_sort(wordIters.begin(), sortedRangeEnd, wordIters.end(),
[](MapIt it1, MapIt it2){ return it1->second > it2->second; });
for (auto it = wordIters.cbegin();
it != sortedRangeEnd;
++it) {
std::printf(" %-10s%10zu\n", (*it)->first.c_str(), (*it)->second);
}
}
int main(int argc, const char** argv) // take list of file names on command line,
{ // print 20 most common words within;
// process files concurrently
std::vector<std::future<WordCountMapType>> futures;
for (int argNum = 1; argNum < argc; ++argNum) {
futures.push_back(std::async([=]{ return wordsInFile(argv[argNum]); }));
}
WordCountMapType wordCounts;
for (auto& f : futures) {
const auto wordCountInfoForFile = f.get(); // move map returned by wordsInFile
for (const auto& wordInfo : wordCountInfoForFile) {
wordCounts[wordInfo.first] += wordInfo.second;
}
}
std::cout << wordCounts.size() << " words found. Most common:\n" ;
const std::size_t maxWordsToShow = 20;
showCommonWords(wordCounts.begin(), wordCounts.end(),
std::min(wordCounts.size(), maxWordsToShow));
}



