'Can't make my example using std::ranges::copy_if(R&& r, O result, Pred pred, Proj proj = {}) compile
I've reduced the code failing to compile to the one below:
#include <algorithm> // copy_if
#include <iostream> // cout
#include <iterator> // back_inserter
#include <ranges>
#include <string>
#include <vector>
struct A
{
std::string p{};
std::string d{};
};
int main()
{
std::vector<A> v{{"/usr/bin/cat", "blah"}, {"/usr/lib", "foo"}};
std::vector<std::string> o{};
std::ranges::copy_if(
v,
std::back_inserter(o),
[](std::string& p){ return (p.size() > 10); },
&A::p);
}
Visual Studio's error output is quite short: error C7602: 'std::ranges::_Copy_if_fn::operator ()': the associated constraints are not satisfied. It basically points you to check the constraints of copy_if at the algorithm header.
gcc and clang are more detailed. Having a look at a bit of both outputs:
- First, the
copy_ifoverload with a range, an output iterator, a predicate, and a projection, is considered. - But then, the expression
*__o = (std::forward<_Tp>(__t)is evaluated as invalid; where:'_Out&& __o', '_Tp&& __t' [with _Tp = A&; _Out = std::back_insert_iterator<std::vector<std::string>>]
Since we are using a projection (from A& to std::string&), why is it trying to copy an A& instead of a std::string& to o?
The full error output is accessible through the Demo link above.
Solution 1:[1]
Since we are using a projection (from A& to std::string&), why is it trying to copy an A& instead of a std::string& to o?
Because that's what the algorithm does. copy_if always copies the source range into the provided iterator, for each element that satisfies the predicate.
The projection only affects the predicate - it's basically just doing function composition here - but it doesn't affect what the overall algorithm does.
This is true for all projections.
If what you want to copy are just the p subobjects, what you want to do instead is
ranges::copy_if(v | views::transform(&A::p), /* ... */);
Which now changes the source range that you're copying from.
For more on this topic, I wrote a whole post about it.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
