I am trying to compile couple of Functional C++ programs using Ranges feature from the following book:
Functional Programming in C++
by Ivan Cukic, Manning Publishing, 2019
Programs in the book are compiled using Boost Rages Library.
I need to compile using Visual C++ 2022, without the Boost library.
I need your help in fixing the correct ranges include .h files please?
#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include <range/v3/view.hpp>
#include <range/v3/action.hpp>
#include <range/v3/istream_range.hpp>
#include <range/v3/to_container.hpp>
usingnamespace ranges::v3;
template <typename T>
class err;
template <typename Range>
void write_top_10(const Range& xs)
{
auto items =
// Assigning the index to each of the movies.
// view::ints(1) gives us an infinite range of integers
// starting with 1. Zipping it with xs will give us
// a range of pairs. The number of items in this range
// will be the size of xs.
view::zip(xs, view::ints(1))
| view::transform([] (constauto& pair) {
return std::to_string(pair.second) +
" " + pair.first;
})
| view::take(10);
for (constauto& item: items) {
std::cout << item << std::endl;
}
}
int main(int argc, char *argv[])
{
std::vector<std::string> movies_1 {
"Meaning of life",
"Dr Strangelove"
};
// If there are less than 10 movies in the vector,
// all will be printed. If there are more than 10
// movies in the vector, only the first 10 will be printed
write_top_10(movies_1);
}
#include <iostream>
#include <vector>
#include <functional>
#include <range/v3/view.hpp>
#include <range/v3/action.hpp>
#include <range/v3/istream_range.hpp>
#include <range/v3/to_container.hpp>
usingnamespace ranges::v3;
usingnamespace std::placeholders;
std::string string_to_lower(const std::string &s) {
return s | view::transform(tolower);
}
std::string string_only_alnum(const std::string &s) {
return s | view::filter(isalnum);
}
int main(int argc, char *argv[])
{
constint n = argc <= 1
? 10
: atoi(argv[1]);
constauto words =
// Getting a range of words (tokens) from cin
istream_range<std::string>(std::cin)
// Converting all words to lower-case
| view::transform(string_to_lower)
// Removing non alphanumeric characters from the words
| view::transform(string_only_alnum)
// Some words could have only contained non alphanumeric characters
| view::remove_if(&std::string::empty)
// For sorting, we need a random-access collection
| to_vector | action::sort;
constauto results =
words
// Grouping the same words
| view::group_by(std::equal_to<>())
// Creating a pair that consists of a word and its
// frequency
| view::transform([] (constauto &group) {
constauto begin = std::begin(group);
constauto end = std::end(group);
constint count = distance(begin, end);
const std::string word = *begin;
return std::make_pair(count, word);
})
// Sorting the resulting range by word frequencies
| to_vector | action::sort;
for (auto value: results | view::reverse // Most frequent words first
| view::take(n) // Taking the top `n` results
) {
std::cout << value.first << " " << value.second << std::endl;
}
return 0;
}
#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include <ranges>
usingnamespace std::ranges;
template <typename T>
class err;
template <typename Range>
void write_top_10(const Range& xs)
{
auto items =
// Assigning the index to each of the movies.
// view::ints(1) gives us an infinite range of integers
// starting with 1. Zipping it with xs will give us
// a range of pairs. The number of items in this range
// will be the size of xs.
views::zip(xs, views::iota(1))
| views::transform([] (constauto& pair) {
return std::to_string(pair.second) +
" " + pair.first;
})
| views::take(10);
for (constauto& item: items) {
std::cout << item << std::endl;
}
}
int main(int argc, char *argv[])
{
std::vector<std::string> movies_1 {
"Meaning of life",
"Dr Strangelove"
};
// If there are less than 10 movies in the vector,
// all will be printed. If there are more than 10
// movies in the vector, only the first 10 will be printed
write_top_10(movies_1);
}
The changes I made were:
* Include <ranges> instead of <range/v3/...>
* Replace usingnamespace ranges::v3; with usingnamespace std::ranges;.
* Replace view with views.
* Replace view::ints(1) with views::iota(1).
Note that zip is very new, it's being added in C++23 which hasn't been officially published yet, so I don't know if Visual C++ supports it yet.
If I install 12.2, will the above two programs compile?
I don't think the second will compile without using Boost - as per my comment above, AFAIK there's no action or group_by in std::ranges yet (even in C++23).
PS
Boost Rages Library
Quite right! Trying to get ranges code to compile can certainly cause a rage!
...
This page is a "brief" summary of some of the huge number of improvements in GCC 13.
...
Note: GCC 13 has not been released yet, so this document is a work-in-progress.
...
Improved experimental support for C++23, including:
Additions to the <ranges> header: views::zip, views::zip_transform, views::adjacent, views::adjacent_transform views::pairwise, views::slide, views::chunk, views::chunk_by.
...