2

I'm interested in a C++17 answer.

Here's a short example

#include <algorithm>
#include <range/v3/algorithm/sort.hpp>
#include <vector>

struct A {
    int x;
    A(int x) : x{x} {}
};

bool operator<(A const& a1, A const& a2) { // if this is here,
    return a1.x < a2.x;
}

int main()
{
    std::vector<A> v{A{1},A{3},A{6},A{5},A{2},A{0},A{4}};
    std::sort(v.begin(), v.end()); // then this compiles and works,
    //ranges::sort(v);             // but this doens't compile!
}

The error isn't particularly intimidating, but I don't really understand it

hello.cpp:17:17: error: no match for call to ‘(const ranges::sort_fn) (std::vector<A>&)’                                                                                                                                                                    
   17 |     ranges::sort(v); // doens't compile                                                                                                                                                                                                                
      |     ~~~~~~~~~~~~^~~                                                                                                                                                                                                                                    
In file included from /usr/include/range/v3/range_fwd.hpp:25,                                                                                                                                                                                                  
                 from /usr/include/range/v3/algorithm/sort.hpp:39,                                                                                                                                                                                             
                 from hello.cpp:2:                                                                                                                                                                                                                          
/usr/include/range/v3/algorithm/sort.hpp:201:11: note: candidate: ‘template<class I, class S, class C, class P, bool CPP_true, typename std::enable_if<(sortable<I, C, P> && CPP_true), int>::type <anonymous>, typename std::enable_if<(random_access_iterator
<I> && CPP_true), int>::type <anonymous>, typename std::enable_if<(sentinel_for<S, I> && CPP_true), int>::type <anonymous> > I ranges::sort_fn::operator()(I, S, C, P) const’                                                                                  
  201 |         I RANGES_FUNC(sort)(I first, S end_, C pred = C{}, P proj = P{})                                                                                                                                                                               
      |           ^~~~~~~~~~~                                                                                                                                                                                                                                  
/usr/include/range/v3/algorithm/sort.hpp:201:11: note:   template argument deduction/substitution failed:                                                                                                                                                      
hello.cpp:17:17: note:   candidate expects 4 arguments, 1 provided                                                                                                                                                                                          
   17 |     ranges::sort(v); // doens't compile                                                                                                                                                                                                                
      |     ~~~~~~~~~~~~^~~                                                                                                                                                                                                                                    
In file included from /usr/include/range/v3/range_fwd.hpp:25,                                                                                                                                                                                                  
                 from /usr/include/range/v3/algorithm/sort.hpp:39,                                                                                                                                                                                             
                 from hello.cpp:2:                                                                                                                                                                                                                          
/usr/include/range/v3/algorithm/sort.hpp:218:9: note: candidate: ‘template<class Rng, class C, class P, bool CPP_true, typename std::enable_if<(sortable<decltype (ranges::_::begin(declval<Rng&>())), C, P> && CPP_true), int>::type <anonymous>, typename std
::enable_if<(random_access_range<Rng> && CPP_true), int>::type <anonymous> > ranges::borrowed_iterator_t<Rng> ranges::sort_fn::operator()(Rng&&, C, P) const’                                                                                                  
  218 |         RANGES_FUNC(sort)(Rng && rng, C pred = C{}, P proj = P{}) //                                                                                                                                                                                   
      |         ^~~~~~~~~~~                                                                                                                                                                                                                                    
/usr/include/range/v3/algorithm/sort.hpp:218:9: note:   template argument deduction/substitution failed:                                                                                                                                                       
In file included from /usr/include/range/v3/range_fwd.hpp:22,                                                                                                                                                                                                  
                 from /usr/include/range/v3/algorithm/sort.hpp:39,                                                                                                                                                                                             
                 from hello.cpp:2:                                                                                                                                                                                                                          
/usr/include/range/v3/algorithm/sort.hpp:216:54: error: no type named ‘type’ in ‘struct std::enable_if<false, int>’                                                                                                                                            
  216 |             requires sortable<iterator_t<Rng>, C, P> AND random_access_range<Rng>)                                                                                                                                                                     
      |

(Related -specific question here.)

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Enlico
  • 23,259
  • 6
  • 48
  • 102
  • Did you mean to do `#include `? – super Sep 07 '21 at 06:30
  • @super, no, I had _**intentionally**_ used the `c++17` tag as well to communicate that I was not happy with a c++20-only answer, but somebody totally ignored it and closed my question. Voting to reopen. I've removed the c++20-specific tags to make things easier. – Enlico Sep 07 '21 at 06:31
  • What is the error you get? – Retired Ninja Sep 07 '21 at 06:39
  • 1
    @Enlico I don't see how tagging with both range-v3/c++17 and std-ranges/c++20 causes anything but confusion. Question looks good now though. :-) – super Sep 07 '21 at 06:42
  • Could it be that it simply wasn't implemented correctly in c++17? – Fantastic Mr Fox Sep 07 '21 at 06:45
  • @Enlico: "*no, I had intentionally used the c++17 tag as well to communicate that I was not happy with a c++20-only answer*" It's the same answer either way; it's just the case that C++20 happens to have a more convenient way to declare all of the operators. But Ranges v3 requires them for the same reason that `std::ranges` does. – Nicol Bolas Sep 07 '21 at 07:04
  • I still think you (good) answer there doesn't apply here verbatim. – Enlico Sep 07 '21 at 07:05
  • @Enlico: It doesn't have to be verbatim to be a duplicate. The core of the answer is the same. I could copy everything but the last two paragraphs over, do a quick find/replace on `ranges::less` for `ranges::sort`, and that'd be that. Ranges v3 is essentially the C++20 ranges library, only with more stuff. – Nicol Bolas Sep 07 '21 at 07:06
  • [`ranges::sort`](https://ericniebler.github.io/range-v3/group__group-algorithms.html#ga008113a56544984350e5a0ab428acccd) uses [`ranges::less`](https://ericniebler.github.io/range-v3/structranges_1_1less.html) which requires [`totally_ordered_with`](https://ericniebler.github.io/range-v3/namespaceconcepts.html#a15e56717f7bd8a5fbadcbc0993ae0d99) so I agree with @NicolBolas the answer for `ranges::v3` is the same as for `std::ranges` – Alan Birtles Sep 07 '21 at 07:14
  • If my question is tagged c++17 (only, since my edit), `totally_odered` is not a thing, so I wouldn't expect a `std::sort`-namesake algorithm to play by other rules. In other words I understand that `std::ranges::sort` wants `std::ranges::less::operator()`, but `ranges::sort` is in C++17 too, so I expected it to work with those "rules". – Enlico Sep 07 '21 at 07:14
  • 2
    @Enlico range-v3 is the prototype for c++20's ranges so it has the same behaviour and uses its own `less` rather than `std::less` (for the same reasons mentioned in @NicolBolas's answer) – Alan Birtles Sep 07 '21 at 07:16
  • @AlanBirtles I missed the part that it uses it's own `less`. Apologies, the dupe does apply then. – Enlico Sep 07 '21 at 07:20

0 Answers0