Hi, I tried to take another approach at UFCS, Here
It isn't professionally written I tried my best.
FYI, if you were to elevate this into an actual WG21 proposal, it would need to have a real person's name on it, not "Shady".
FYI,
your Clang patch seems to have a lot of extraneous diffs. I bet you ran `clang-format` on the entire codebase, or on the files you touched. Don't do that. Instead, run `git-clang-format --diff --extensions ',h,cpp' HEAD~4 --` to format only the exact diffs that you made, leaving the rest of the file's formatting intact.
The idea seems identical to the pre-existing (and apparently stalled/abandoned)
P2011 proposal of a "pipeline operator" — with two differences:
(1) You use the existing token `.` instead of P2011's new "pizza operator" `|>` (which required lexers to change to accept `|>` as a single token).
(2) You limit the right-hand-side "operand" to begin lexically with `identifier ::` in addition to whatever P2011 says.
Your discussion of CWG 1089 focuses on `p->T::f()`, not `p.T::f()`. Are you trying to propose that `p -> T::f()` should act the same as your new `(*p) . T::f()`, or differently from it? Either way seems bad. IMHO the original sin here was trying to reuse `.` as the pipeline operator, instead of picking a completely new operator like P2011's `|>`.
It's unclear to me (since you didn't provide wording) whether you intend to support both
int x1 = 1;
int y1 = x . std::max(2);
(where lookup finds an overload set of function templates) and also
int x2 = 1;
int y2 = x . std::ranges::max(2);
(where lookup finds a single global variable, which happens to be a niebloid). Ctrl+F for "ranges::", "nieb", "cpo" didn't find any discussion of what you mean by "only finds free functions."
Come to think of it, it's also unclear what you would do with:
struct S { int f(int); static float f(S&, int); };
S s;
int y3 = s . S::f(2);
Is this now going to be rewritten into `S::f(s, 2)`, or will you keep the old behavior and make it call `s.f(2)`? Does anything change if the name `S` in this context refers to a namespace?
Godbolt: namespace N {
struct S {
int f(int) { return 1; }
static int f(S&, int) { return 2; }
};
}
namespace S {
int f(N::S&, int) { return 3; }
}
int main() {
N::S s;
return s.S::f(2); // today this returns 1
}
return s |> S::f(2); // today this is illegal; tomorrow it rewrites into S::f(s, 2) and therefore returns 3, no ambiguity at all
Basically, you have some minor procedural problems with the proposal, and then you have a major fatal flaw due to your trying to reuse `.` (and maybe `->`?) as your pipeline operator instead of inventing a new one.