ericniebler / range-v3

Range library for C++14/17/20, basis for C++20's std::ranges
Other
4.06k stars 437 forks source link

Cannot easily use ref-qualified member functions as projections #1705

Open Talkless opened 2 years ago

Talkless commented 2 years ago

This call fails to compile:

const auto it{ranges::find(values, stringToFind, &Value::value)};

with:

error: no match for call to '(const ranges::find_fn) (const std::vector<Value>&, const std::string&, <unresolved overloaded function type>)'

...

note:   couldn't deduce template parameter 'V'

when member function value has ref-qualified overloads:

[[nodiscard]] std::string value() &;
[[nodiscard]] const std::string &value() const& noexcept;
[[nodiscard]] std::string &&value() && noexcept;

I can make it work by using lambda as projection, or static_cast'ing member function to specific signature, but these solutions are too verbose and just loses the beauty of projections...

Full example here: https://godbolt.org/z/ddj5qE1EE

I guess it's "wontfix", but maybe there's is some magic template trickery to select best overload..?

JohelEGP commented 2 years ago

This could work: https://godbolt.org/z/q4eTeM6dT.

It'd have to be properly integrated with projections. I haven't checked to see if that's possible. Projections already default to std::identity, so overloading might be necessary. It could also be a breaking change for things convertible to a member pointer.

ericniebler commented 2 years ago

It would be nice to fix this.

brevzin commented 2 years ago

Is this really a projection issue? This is just one example of part of a broader problem of passing overload sets into function templates.

I feel like this either requires a language feature to create the overload set, or a language feature to perform overload resolution during template deduction time to bind which overload you want (by going through the constraint somehow).

JohelEGP commented 2 years ago

or a language feature to perform overload resolution during template deduction time to bind which overload you want

Like https://wg21.link/P1167?

brevzin commented 2 years ago

or a language feature to perform overload resolution during template deduction time to bind which overload you want

Like https://wg21.link/P1167?

No, that's about class templates?

What I meant was something like:

template <class F> requires invocable<F, int const&, int const&>
void algo(F );

// this is ill-formed today, but we know we need to call this with (int const&, int const&)
// and those arguments do find a unique overload, so we could hypothetically pick it
algo(std::max);
JohelEGP commented 2 years ago

I meant the part titled "Deduction guides for function templates".

brevzin commented 2 years ago

I meant the part titled "Deduction guides for function templates".

I don't see how that's relevant either.

JohelEGP commented 2 years ago

I supposed that could be used to solve the problem in the OP, but not necessarily the broader problem you describe.

brevzin commented 2 years ago

I supposed that could be used to solve the problem in the OP, but not necessarily the broader problem you describe.

The problem in OP is passing an overloaded name into a function template, which can't deduce. Having function template deduction guides still requires deduction to have succeeded first.

JohelEGP commented 2 years ago

That's true.

Talkless commented 1 year ago

Sorry, I don't grok your discussion. Can it be fixed in Ranges library, or this needs new C++ language feature?

Talkless commented 1 year ago

Any ideas how "deducing this" C++23 feature will help (or not)?

It will allow to write single template function for all ref-qualified overloads: https://youtu.be/b0NkuoUkv0M?t=188 (3:08).

JohelEGP commented 1 year ago

As projections, they need to be treated like you would a template function.