0

I'm exploring the ranges functions.

struct User
{
    std::string name;
    int age;
    std::string gender;

    template<class Os> friend
        Os& operator<<(Os& os, User const& u)
    {
        return os << "\n" << std::right << std::setw(10)
            << u.name << " - " << u.age << ", " << u.gender;
    }
};

std::vector<User> users = {
    {"Dorothy", 59, "F"},
    {"Allan", 60, "M"},
    {"Kenny", 33, "M"},
    {"Jaye", 30, "F"}
};

int main()
{
    std::cout << "Count of M users: " <<
         std::ranges::count_if(users, [](const User& u) {return u.gender == "M"; }) << 
         std::endl;
    
    const User match { "Ed", 44, "M" };

    std::cout << "Count of Ed users: " <<
         std::ranges::count(users, match) <<
         std::endl;
}

The count_if functions as expected. The count expression generates an error in MSVS 2019.

Error C7602 'std::ranges::_Count_fn::operator ()': the associated constraints are not satisfied D:\Test\Code\Ranges\Ranges.cpp

and it points me to the std algorithm header. I'm clearly not understanding the indirect_binary_predicate that is the only constraint listed for the count function. Reading cppreference.com is...unhelpful :-).

What am I missing here?

SimpleCoder
  • 45
  • 1
  • 8

1 Answers1

2

In std::ranges::count_if you're providing a custom comparator. However, in std::ranges::count you're trying to use the default comparison, which doesn't.

You need to provide that, and assuming you want member-wise comparison of the struct members, you can simply add:

auto operator<=>(User const &) const = default;

to your struct.

If you want a different kind of comparison, you have to specify that instead of using = default.

cigien
  • 57,834
  • 11
  • 73
  • 112
  • Thanks that worked (I had no doubt :-)) I almost had it when I tried to add an operator==() to the struct but I didn't catch a typo and got errors in previously working code. This solves the same problem with any algorithm, such as ranges::replace, that need to traverse the container and making comparisons. – SimpleCoder Feb 28 '21 at 01:16
  • @SimpleCoder Yes, if you just want *comparisons*, all you actually need is the `operator==`. And, of course, you have to spell it correctly :) – cigien Feb 28 '21 at 01:24