When it comes to programming languages, I literally use dozens, but when it comes down to an all other things being equal decision my go to language of choice tends to be C#. One of the big plus sides of C# is the wonderful LINQ ( Language Integrated Query ). LINQ makes heavy use of lambda (closures) a feature lacking until recently in C++. Now with lambda expressions part of the C++ language LINQ for C++ is now a possibility. It exists as a single hpp file you add to your project.
If you aren’t already familiar with LINQ, here is a simple example in C#. It’s a simple scoreboard that sorts the results by name, then by score, then totals and averages all of the scores. As you can see, it’s a very compact and clean way to access data.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApplication1 { class Entry { public Entry(string name, int score) { this.name = name; this.score = score; } public string name { get; set; } public int score { get; set; } } class Program { static void Main(string[] args) { List<Entry> scoreEntries = new List<Entry>(); scoreEntries.Add(new Entry("mike", 42)); scoreEntries.Add(new Entry("bob", 99)); scoreEntries.Add(new Entry("doug", 99)); scoreEntries.Add(new Entry("steve", 12)); var sortedByName = scoreEntries.OrderBy(item => item.name).ToList(); Console.WriteLine("Sorted by score"); sortedByName.ForEach(item => { Console.WriteLine(item.name + " " + item.score); }); Console.WriteLine("nSorted by name"); var sortedByScore = scoreEntries.OrderBy(item => item.score).ToList(); sortedByScore.ForEach(item => { Console.WriteLine(item.name + " " + item.score); }); var totalOfScores = scoreEntries.Where(item => item.score > 0) .Sum(item => item.score); var averageScore = scoreEntries.Average(item => item.score); Console.WriteLine("nTotal of scores == " + totalOfScores + " Average Score == " + averageScore); } } }
Now let’s take a look at the C++ version using cpplinq:
#include <string> #include <list> #include "cpplinq.hpp" #include <iostream> class Entry{ public: Entry::Entry(std::string name, int score){ this->name = name; this->score = score; } std::string name; int score; }; int main(int argc, char **argv) { std::list<Entry> scoreEntries; scoreEntries.push_back(Entry("mike", 42)); scoreEntries.push_back(Entry("bob", 99)); scoreEntries.push_back(Entry("doug", 99)); scoreEntries.push_back(Entry("steve", 12)); using namespace cpplinq; auto sortedByName = from(scoreEntries) >> orderby_ascending([](const Entry & entry){ return entry.name; }) >> to_vector(); auto sortedByScore = from(scoreEntries) >> orderby_descending([](const Entry & entry){ return entry.score; }) >> to_vector(); std::cout << "Sorted by name" << std::endl; from(sortedByName) >> for_each([](const Entry & entry){ std::cout << entry.name << " " << entry.score << std::endl; }); std::cout << std::endl << "Sorted by score" << std::endl; from(sortedByScore) >> for_each([](const Entry & entry){ std::cout << entry.name << " " << entry.score << std::endl; }); auto totalOfScores = from(scoreEntries) >> select([](const Entry & entry){ return entry.score; }) >> sum(); auto averageScore = from(scoreEntries) >> select([](const Entry & entry){ return entry.score; }) >> avg(); std::cout << std::endl << "Total of scores == " << totalOfScores << " average score == " << averageScore << std::endl; return 0; }
A few obvious differences. Cpplinq statements start with the from methods defining the type of data source to perform on. In this case I used the default from() which takes a standard C++ STL type. There are also from__array() and from_range() for working with arrays and iterators respectively. Next the . (dot) operator has been replaced with the >> operator. Of course the lambda syntax is different as well ( C++’s is much uglier ), otherwise at the end of the day, it is very similar to LINQ in both look and execution.
If you are new to C++ and are struggling to wrap your head around the uses for lambdas, give cpplinq a shot and you will quickly see their value!