Search code examples
c++c++17header-filesrange-v3

Compilation fails after switching included headers' order for range-v3


When I use views::set_intersection and views::transform together in range-v3 v0.12.0, the order of the headers range/v3/view/set_algorithm.hpp and range/v3/view/transform.hpp matters. If the former header is included first, the code will not compile. The opposite order compiles well.

This is a minimal example: (see also https://godbolt.org/z/nhK1s3xdv for a live demo)

#include <iostream>
#include <map>

// this order fails to compile, however, switch the order, it compiles
#include <range/v3/view/set_algorithm.hpp>
#include <range/v3/view/transform.hpp>

int main () {
    std::map<int, int> m1 {{0, 0}, {1, 1}, {2, 2}};
    std::map<int, int> m2 {{0, 0}, {2, 1}, {3, 2}};
    {
        std::cout << "set_intersection\n";
        auto res = ranges::views::set_intersection(m1, m2);
        for(auto&& p : res) {
            std::cout << p.first << ' ' << p.second << '\n';
        }
    }

    {
        std::cout << "set_intersection\n";
        auto res = m1 | ranges::views::set_intersection(m2);
        for(auto&& p : res) {
            std::cout << p.first << ' ' << p.second << '\n';
        }
    }
    {
        std::cout << "set_intersection and pipe\n";
        auto res = ranges::views::set_intersection(m1, m2)
                     | ranges::views::transform(
                        [](auto&& p) { return 0; });
    }

    return 0;
}

Interestingly, the error message is

error: use of undeclared identifier 'bind_back'
                return make_view_closure(bind_back(set_intersection_base_fn{},

for this line

auto res = m1 | ranges::views::set_intersection(m2);

Which is nothing to do with views::transform.

I searched bind_back, and it's defined in meta/meta.hpp, and it's already included in view/set_algorithm.hpp.

I don't understand where the bug is.


Solution

  • With templates inclusion order matters. range-v3 is heavily templated and it's best not to deviate from the documentation on which headers to include. The bind_back you found is nested in a namespace meta. The bind_back you need is defined in bind_back.hpp, see the range-v3 documentation.