> > 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