> > Now with that out of the way, I do still kind of feel icky about it.
> > This really is a MASSIVE edge case that will almost never matter. As
> > far as I know, instantiating explicitly like so...
> >
> > auto f = [x = 42](this auto&&) -> int { return x; };
> > int (*fp)(int&) = &decltype(f)::operator();
> >
> > ...is the only way to coerce the explicit object parameter of the
> > lambda's call operator into deducing as an unrelated type. Cases that
> > are not deduced can be caught trivially while parsing the lambda and
> > are the only reasonable cases where you might have an unrelated type.
> > Perhaps it might become relevant in the future if a proposal like
> > https://atomgalaxy.github.io/isocpp-1107/D1107.html ever made it in,
> > but we aren't there yet. So as it stands, I'm pretty certain that it's
> > just impossible to instantiate a lambda's call operator with an
> > unrelated xobj parameter type except for the above case with
> > address-of. If you can think of another, please do share, but I've
> > spent a fair amount of time on it and came up with nothing.
>
>
> I think you're right.
>
I was about to send a quick e-mail amending this, before I respond to
everything else I want to include this test case I just came up with minutes
ago.
template<typename T>
struct S : T {
using T::operator();
operator int() const {return {};}
};
int main()
{
auto s0 = S{[](this auto&& self) { return self; }};
auto s1 = S{[x = 0](this auto&& self) { return self; }};
s0.operator()<int>();
s1.operator()<int>();
}
So I was wrong, but, the good news is that this does demonstrate that there
is a code path where my diagnostic works.
template<typename T>
concept NotInt = (!__is_same (T, int));
template<bool> struct enable_if {};
template<> struct enable_if<true> { using type = decltype(nullptr); };
template<bool B> using enable_if_t = typename enable_if<B>::type;
template<NotInt T>
void using_concepts(T) {}
template<typename T, enable_if_t<!__is_same (T, int)> = nullptr>
void using_enable_if(T) {}
void test()
{
void (*fp_concepts)(int) = &using_concepts;
void (*fp_enable_if)(int) = &using_enable_if;
using_concepts(0);
using_enable_if(0);
}
I also have this test case that demonstrates the difference in diagnostic
quality. This is unrelated to explicit object member functions though, but
it does demonstrate that the diagnostics that I currently produce are in
equal quality to the ones already produced in these cases.
At this point I feel like I am unlikely to start fixing the bug with
captures not being treated as const tonight. Cleaning up the tests is taking
me longer than I thought.
Anyway I'm just rushing this e-mail to clarify this mistake, admittedly I am
a little excited to have found (which in hindsight should have been obvious)
a test case that more directly calls a lambda's call operator with an
unrelated type.
Alex