Need help in fixing include .h file

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?

Thanks and best regards,


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#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>

using namespace 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([] (const auto& pair) {
                    return std::to_string(pair.second) +
                           " " + pair.first;
            })
            | view::take(10);

    for (const auto& 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);
}



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#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>

using namespace ranges::v3;
using namespace 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[])
{
    const int n = argc <= 1
                    ? 10
                    : atoi(argv[1]);

    const auto 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;


    const auto 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([] (const auto &group) {
                         const auto begin       = std::begin(group);
                         const auto end         = std::end(group);
                         const int  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;
}



Last edited on
I'm not an expert on the ranges library but I was able to get the first code to compile using the latest development version of GCC...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <functional>
#include <iostream>
#include <string>
#include <vector>

#include <ranges>

using namespace 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([] (const auto& pair) {
                    return std::to_string(pair.second) +
                           " " + pair.first;
            })
            | views::take(10);

    for (const auto& 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 using namespace ranges::v3; with using namespace 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.
Last edited on
Also ranges::to_vector becomes ranges::to<std::vector> (C++23)

AFAIK, there's no action or group_by in std::ranges.

The views::zip currently doesn't compile with VS 17.4.2 (using Peter87's code above).
Last edited on
Thank you very much Peter87 and seeplus for the information.

MS VS2022 17.4.2 is giving following error:


Error	C2039	'zip': is not a member of 'std::ranges::views'



Hello Peter87,
Is GCC version you have used 12.2 released on Aug 19, 2022 ?

I have a Ubuntu Linux laptop.
If I install 12.2, will the above two programs compile?

Thanks,
Last edited on
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!
Is GCC version you have used 12.2 released on Aug 19, 2022 ?

No. It's an unofficial work-in-progress version for GCC 13.

It won't work with SDL 12.2 I'm afraid.

https://gcc.gnu.org/gcc-13/changes.html
...
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.
...
Topic archived. No new replies allowed.