From §4.2.7 of the proposal http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html#pathological-cases
It said that:
These are even more unlikely to be actually useful code. In this example,
Bis neither convertible toAnorint, so neither of these functions is even invocable using normal member syntax. However, you could take a pointer to such functions and invoke them through that pointer.(&B::bar)(42)is valid, if weird, call.
However, It does not specify whether the standard does not allow explicit object parameter of type-of-self implicitly convertible to particular another type.
struct A { };
struct B {
void foo(this A&);
void bar(this int);
};
Does that mean that:
struct A { };
struct B {
operator A() const noexcept;
void foo(this A);
};
// ...
// '&B::foo' is of type function pointer not pointer to member function
// because it uses explicit object parameter.
(&B::foo)(A{});
(&B::foo)(B{});
B{}.foo(); // will work?
will work?
In another case, here is a lambda. Since the type of the lambda is unutterable and is always dependent. What about the case above? (this captureless lambda is convertible to int(*)(int, int, int))
auto fib = [](this int(* self)(int, int, int), int n, int a = 0, int b = 1) {
return n == 0 ? a : n == 1 ? b : self(n - 1, b, a + b);
};
Given that:
Non-member functions, static member functions, and explicit object member functions match targets of function pointer type or reference to function type. Non-static Implicit object member functions match targets of pointer-to-member-function type. ([over.match.viable] §12.2.3)
In all contexts, when converting to the implicit object parameter or when converting to the left operand of an assignment operation only standard conversion sequences are allowed. [Note: When converting to the explicit object parameter, if any, user-defined conversion sequences are allowed. - end note ] ([over.best.ics] §12.2.4.2)
For your first question:
Yes. Candidate lookup will find
B::foo, which more or less evaluates asfoo(B{}), which is valid due to the conversion function. This is explicitly called out in the note you cited, in [over.ics.best]/7:This one, I'm actually not entirely sure about:
It seems exceedingly unlikely to be useful and you should probably never do this, so I don't know that it matters whether or not it's actually valid. But also am not sure what it means for examples like this:
If this is convertible to a function pointer, what function pointer type exactly? If it's
void(*)(), then whichCare we invokingf()on? So it'd kind of have to bevoid(*)(C), in which case thefibexample definitely does not work because it's impossible to spell the function pointer type non-generically in a way that matches.