KDAB / KDAlgorithms

Algorithm wrappers
Other
82 stars 15 forks source link

work with std::range::subrange #68

Closed hmoffatt closed 2 months ago

hmoffatt commented 5 months ago

Possibly related to #4 is it possible to make the algorithms work with subranges?

Occasionally I need to use an algorithm on a subset of a container. I like using kdalgorithms rather than STL because kdalgorithms::transformed for example returns the new container rather than requiring it to be declared in advance.

I tried this; all_of compiles, but transformed does not, complaining about missing value_type in the subrange (in MSVC 2022):

    std::vector<int> test;
    auto x = kdalgorithms::all_of(std::ranges::subrange(test.cbegin(), test.cend()),
        [](const int i) -> bool { return i == 0; });

    auto y = kdalgorithms::transformed<std::vector<int>>(std::ranges::subrange(test.cbegin(), test.cend()),
        [](const int i) -> int { return i + 1; });
jesperkdab commented 4 months ago

Thanks for the feedback. I looked shortly at subrange, and indeed I see no value_type in there, which is all over the place for kdalgorithms. I've very little insight into how std::ranges works, so I'm afraid I realistically wouldn't get to fix this.

I'll leave it open in case someone else knows of a way around this (without a huge rewrite to KDAlgorithms)

Cheers Jesper.

hmoffatt commented 4 months ago

It looks like there is std::ranges::range_value_t<> for this.. I don't know if this fits in with your ValueTypeHelper though. https://stackoverflow.com/questions/74496713/how-to-get-the-type-of-the-values-in-a-c20-stdranges-range

jesperkdab commented 2 months ago

Please try https://github.com/KDAB/KDAlgorithms/pull/70 which at least works with your example now.

hmoffatt commented 2 months ago

Looks good! I tried a few things with QVector and std::vector and it worked as expected, on g++/clang++/MSVC.

I tried working on a subrange of std::map and didn't have much luck:

        std::map<int, QString> test;
        test[0] = "hi";
        test[1] = "there";

        for (auto it = test.begin(); it != test.end(); it++)
            qDebug() << *it; // ok

        auto sub = std::ranges::subrange(test.cbegin(), test.cend());

        for (auto [k, v] : sub) // doesn't compile with clang++ 14
            qDebug() << k << v;

        qDebug() << kdalgorithms::transformed<std::vector<QString>>(sub,
            [](const auto& v) -> QString { return v.second; });

clang++-16 returns

In file included from ./kdalgorithms.h:25:
./kdalgorithms_bits/transform.h:45:39: error: invalid reference to function 'size': constraints not satisfied
        detail::reserve(result, input.size());
                                      ^
./kdalgorithms_bits/transform.h:73:16: note: in instantiation of function template specialization 'kdalgorithms::detail::transformed<std::vector<QString>, std::ranges::subrange<std::_Rb_tree_const_iterator<std::pair<const int, QString>>, std::_Rb_tree_const_iterator<std::pair<const int, QString>>, std::ranges::subrange_kind::unsized> &, (lambda at test.cpp:50:13)>' requested here
        return transformed<ResultContainer>(std::forward<InputContainer>(input),
               ^
./kdalgorithms_bits/transform.h:108:20: note: in instantiation of function template specialization 'kdalgorithms::detail::transformed<std::vector<QString>, std::ranges::subrange<std::_Rb_tree_const_iterator<std::pair<const int, QString>>, std::_Rb_tree_const_iterator<std::pair<const int, QString>>, std::ranges::subrange_kind::unsized> &, (lambda at test.cpp:50:13)>' requested here
    return detail::transformed<ResultContainer>(
                   ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../include/c++/12/bits/ranges_util.h:327:30: note: because '(std::ranges::subrange_kind)false == subrange_kind::sized' evaluated to false
      size() const requires (_Kind == subrange_kind::sized)
                             ^

Similar with g++ 12 and VS 2022.

My only interest is in a subrange of a vector currently anyway. Thanks for working on this.

jesperkdab commented 2 months ago

Implemented.