Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

cpplinq: Range Generators and Conversion Operators

5.00/5 (1 vote)
23 Nov 2012CPOL2 min read 8.6K  
In this post, I will discuss range generators and range conversion operators.

In my previous post, I introduced cpplinq, a C++ template library that provides .NET-like query operators for sequences of objects in C++11. In this second installment, I will discuss about two things: range generators and range conversion operators. These two sets of operators are ubiquitous in queries.

Range Generators

A range generator builds an object that represents the range on which query operators are applied. The library provides several such generators:

  • from_iterators: constructs a range from a pair of iterators
  • from: constructs a range from an STL-like container that provides begin() and end() methods (representing the first and past-the-end elements). This is basically a wrapper on from_iterators operator.
    C++
    std::vector<int> numbers;
    numbers.push_back(1);
    numbers.push_back(2);
    numbers.push_back(3);
    numbers.push_back(4);
    numbers.push_back(5);
    
    auto result = from(numbers);
    result >> for_each([](int i) {std::cout << i << std::endl;});

    This is similar to:

    C++
    auto result = from_iterators(numbers.begin(), numbers.end());
  • from_array: constructs a range from an array.
    C++
    int numbers[] = {1,2,3,4,5};
    auto result = from_array(numbers);
    result >> for_each([](int i) {std::cout << i << std::endl;});

    This is similar to:

    C++
    auto result = from_iterators(arrnumbers, arrnumbers + 5);

In addition to the "from" operators, the library also provides several .NET like range generators:

  • range: generates a range of integral, consecutive numbers, starting with an initial seed and having a specified number of elements.
    C++
    auto result = range(10, 90); // creates a range of numbers in the interval [10, 100)
  • repeat: generates a range by repeating a value a given number of times
    C++
    auto result = repeat("cpplinq", 10); // creates a range with 10 strings with the value "cpplinq"
  • empty: returns an empty range of a given type
    C++
    auto result = empty<customer>(); // creates an empty range of customers

Range Conversion Operators

A conversion operator folds a range into a container that holds the values of the range. There are several such conversion operators that the library provides.

  • to_vector: creates a std::vector<TValue> from a range, where TValue is the type of the elements of the range.
    C++
    auto result = range(1, 10) >> to_vector();
    
    std::list<int> numbers;
    auto result = from(numbers) >> to_vector(); // transforms a list into a vector
  • to_list: creates a std::list<TValue> from a range, where TValue is the type of the elements of the range.
    C++
    auto result = range(1, 10) >> to_list();
  • to_map: creates a std::map<TKey, TValue> from a range. It takes a predicate that selects the value to use as the key for each element of the range. It implements a one-to-one dictionary that maps keys to single values.
    C++
    // creates a map where key is the customer ID, and the value is the customer object
    auto result = from_array (customers) >> to_map ([](customer const & c){return c.id;});
  • to_lookup: creates a cpplinq::lookup<TKey, TElement> from a sequence. It implements a one-to-many dictionary that maps keys to sequences of values.
    C++
    customer_address customer_addresses[] =
    {
       customer_address (2, 4, "Finland"   ),
       customer_address (3, 4, "USA"       ),
       customer_address (1, 1, "USA"       ),
    };
    
    auto lookup = from_array (customer_addresses) 
               >> to_lookup ([] (customer_address const & ca){return ca.customer_id;}); 
    
    auto countries = lookup[4] 
                  >> select([](customer_address const & ca) {return ca.country;}) 
                  >> to_vector();  // yields {"Finland", "USA"}

License

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