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.
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:
auto result = from_iterators(numbers.begin(), numbers.end());
from_array
: constructs a range from an array.
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:
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.
auto result = range(10, 90);
repeat
: generates a range by repeating a value a given number of times
auto result = repeat("cpplinq", 10);
empty
: returns an empty range of a given type
auto result = empty<customer>();
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.
auto result = range(1, 10) >> to_vector();
std::list<int> numbers;
auto result = from(numbers) >> to_vector();
to_list
: creates a std::list<TValue>
from a range, where TValue
is the type of the elements of the range.
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.
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.
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();
CodeProject