Need help in fixing include .h file

Dec 6, 2022 at 4:55am
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 Dec 6, 2022 at 4:58am
Dec 6, 2022 at 9:17am
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 Dec 6, 2022 at 9:27am
Dec 6, 2022 at 9:48am
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 Dec 6, 2022 at 10:25am
Dec 6, 2022 at 10:42am
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 Dec 6, 2022 at 11:28am
Dec 6, 2022 at 11:50am
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!
Dec 6, 2022 at 12:38pm
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.