aspx">May 2013 (13)
  • April 2013 (21)
  • March 2013 (16)
  • February 2013 (14)
  • January 2013 (15)
  • December 2012 (16)
  • November 2012 (21)
  • October 2012 (23)
  • September 2012 (24)
  • August 2012 (24)
  • July 2012 (25)
  • June 2012 (28)
  • May 2012 (35)
  • April 2012 (26)
  • March 2012 (13)
  • February 2012 (14)
  • January 2012 (13)
  • December 2011 (9)
  • November 2011 (16)
  • October 2011 (11)
  • September 2011 (7)
  • August 2011 (8)
  • July 2011 (7)
  • June 2011 (8)
  • May 2011 (15)
  • April 2011 (11)
  • DisqusCommentsSummary

    Newsletter

    Get notified when a new post is published.


    Calendar

    <<  August 2014  >>
    MoTuWeThFrSaSu
    28293031123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    View posts in large calendar
     

    LINQ for C++ with cpplinq

    4. April 2014

     

    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!

    Programming







    blog comments powered by Disqus