Click here to Skip to main content
Click here to Skip to main content

cpplinq: An introduction

, 23 Nov 2012
Rate this:
Please Sign up or sign in to vote.
cpplinq is a C++ template library that provides .NET-like query operators for sequences of objects in C++11. cpplinq is an open-source library that works both with VC++ compilers (2010 and 2012) and gcc (4.7.0 is the version used for unit tests). The library supports most of the .NET query operators

cpplinq is a C++ template library that provides .NET-like query operators for sequences of objects in C++11. cpplinq is an open-source library that works both with VC++ compilers (2010 and 2012) and gcc (4.7.0 is the version used for unit tests). The library supports most of the .NET query operators and is extendable with additional operators that can suite some particular use. If you’re not familiar with .NET query operators, this article, http://msdn.microsoft.com/en-us/library/bb394939.aspx, lists and explain them.

The light-weighted library consists of a series of template classes and helper methods, provided in a single header under the namespace cpplinq.

This is a short introduction to the library. More posts will follow. Let’s see some examples.

The following code retrieves all the prime numbers from an array.

auto is_prime = [](int i) -> bool 
{
    if (i < 2) { return false; }
    else if (i == 2) { return true; }
    else
    {
        auto r = (int)std::ceil (std::sqrt (i));
        for (auto iter = 2; iter <= r; ++iter)
        {
            if (i % iter == 0) { return false; }
        }
        return true;
    }
};

int numbers[] = {1,2,3,4,5,6,7,8,9};
auto primes = from_array(numbers)
           >> where(is_prime)
           >> to_vector(); // yields {2,3,5,7}

A slightly variation produces a sequence of first N prime numbers and transforms them into strings.

std::vector<string> primes_as_strings(int n)
{
    auto primes = range(0, INT_MAX)
               >> where(is_prime)
               >> take(n)
               >> select([](int i) {std::stringstream s; s << i; return s.str();})
               >> to_vector();

   return primes;
}

The next sample retrieves all the orders from a customer.

struct order 
{
    std::size_t id;
    std::size_t customer_id;
    time_t      date;

    order(std::size_t id, std::size_t cid, time_t date):
        id(id), customer_id(cid), date(date)
    {
    }
};

struct order_line 
{
    std::size_t id;
    std::size_t order_id;
    std::size_t article_id;
    double      quantity;

    order_line(std::size_t id, std::size_t oid, std::size_t aid, double quantity):
        id(id), order_id(oid), article_id(aid), quantity(quantity)
    {
    }
};

order orders[] = 
{
    order(1, 1, time(NULL)),
    order(2, 2, time(NULL)),
    order(3, 1, time(NULL)),
};

order_line orderlines [] = 
{
    order_line(1, 1, 100, 1.0),
    order_line(2, 1, 101, 5.0),
    order_line(3, 1, 102, 2.0),
    order_line(4, 2, 400, 1.0),
    order_line(5, 3, 401, 1.0),
};

void print_orders_by_cust(std::size_t custid)
{
    auto result = from_array(orders)
               >> where([=](order const & o) {return o.customer_id == custid;})
               >> join(from_array(orderlines),
                        [](order const & o) {return o.id;},
                        [](order_line const & ol) {return ol.order_id;},
                        [](order const & o, order_line const & ol) {return std::make_pair(o, ol);});

    result >> for_each([](std::pair<order, order_line> const & p){
        std::cout << "order=" << p.first.id << ", " << ctime(&(p.first.date)) 
                  << "  article=" << p.second.article_id << ", quantity=" << p.second.quantity << std::endl; 
    });
}

Callinq print_orders_by_cust() with argument 1 would print:

order=1, Tue Oct 23 19:22:14 2012
  article=100, quantity=1
order=1, Tue Oct 23 19:22:14 2012
  article=101, quantity=5
order=1, Tue Oct 23 19:22:14 2012
  article=102, quantity=2
order=3, Tue Oct 23 19:23:22 2012
  article=401, quantity=1

On the other hand, if you want to print the last order from a particular customer, the function above would change to something like this:

void print_last_order_for_customer(std::size_t custid)
{
    auto result = from_array(orders)
               >> where([=](order const & o) {return o.customer_id == custid;})
               >> orderby_descending([](order const & o) {return o.date;})
               >> take(1)
               >> join(from_array(orderlines),
                        [](order const & o) {return o.id;},
                        [](order_line const & ol) {return ol.order_id;},
                        [](order const & o, order_line const & ol) {return std::make_pair(o, ol);});

    result >> for_each([](std::pair<order, order_line> const & p){
        std::cout << "order=" << p.first.id << ", " << ctime(&(p.first.date)) 
                  << "  article=" << p.second.article_id << ", quantity=" << p.second.quantity << std::endl; 
    });
}

Calling print_last_order_for_customer() with argument 1 would print:

order=3, Tue Oct 23 19:23:22 2012
  article=401, quantity=1

Hopefully this provides a quick view over the capabilities of the library. In following posts I will show more examples and discuss some of the query operators. To learn more about the library see the following articles:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Marius Bancila
Software Developer (Senior) Visma Software
Romania Romania
Marius Bancila is a Microsoft MVP for VC++. He works as a software developer for Visma, a Norwegian-based company. He is mainly focused on building desktop applications with VC++ and VC#. He keeps a blog at http://www.mariusbancila.ro/blog, focused on Windows programming. He is the co-founder of codexpert.ro, a community for Romanian C++ programmers.
Follow on   Twitter

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 23 Nov 2012
Article Copyright 2012 by Marius Bancila
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid