Path: csiph.com!eternal-september.org!feeder.eternal-september.org!nntp.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c++ Subject: Re: Array size validity and SFINAE Date: Mon, 02 Mar 2026 21:34:23 -0800 Organization: A noiseless patient Spider Lines: 104 Message-ID: <86ecm1easg.fsf@linuxsc.com> References: <10nn6pp$su58$1@dont-email.me> <86zf4qeicj.fsf@linuxsc.com> <10o4bgp$18opb$1@dont-email.me> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Date: Tue, 03 Mar 2026 05:34:28 +0000 (UTC) Injection-Info: dont-email.me; posting-host="9dc790098ce30bad4f358538e3d50880"; logging-data="1839364"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18qGDV1vgZXhgfp5Io/tcTSsrDY45i0euI=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:YEWqXj9lvU/+PuolTJQO+pUiseI= sha1:rrTcWy1yzD89rgTyrWr6okgSivk= Xref: csiph.com comp.lang.c++:123509 Andrey Tarasevich writes: > On Mon 3/2/2026 12:38 AM, Tim Rentsch wrote: > >> First, the struct S is irrelevant; it has no bearing on the >> question or the observed behavior. > > You are right. However, the `foo` call in my code is a remnant of > an experiment with non-existing nested name. It also illustrates the > problem. > > Yet my original intent was to use > > foo(); > > call. > >> Third, if we add a statement >> >> int fred = T::N; >> >> to the first template, gcc gives an error, whereas clang still >> outputs '...'. > > Add where exactly? Into the body of the function template? Yes, just before the std::cout line. > That would > immediately take us out of SFINAE territory and make it a hard error > in cases where `T::N` does not exist. Oh. I still think of that as SFINAE, since clang does the right thing. > Not surprisingly, any compiler > that chooses the first overload will subsequently issue an error. Right. >> Fourth, if after adding 'int fred = ...' to the first template, we >> change the call in main() to >> >> foo(0) >> >> then gcc again outputs 'array', whereas clang outputs '...'. > > That is another facet of the problem I mentioned in my original > question, since array declaration with negative array size is supposed > to be invalid. > > Not sure what importance you assign to that "after adding..." part, > since adding 'int fred = ...' to the first template is completely > beside the point in this case. It's a way of showing gcc is confused, since there is another template that doesn't have an error, which clang correctly recognizes. >> Fifth, if after adding 'int fred = ...' to the first template, we >> define a new struct >> >> struct U { static constexpr unsigned int N = -1; }; >> >> and change the invocation in main() to >> >> foo(0) >> >> then both gcc and clang both output 'array'. > > This is expected, of course. Again, adding 'int fred = ...' to the > first template has no bearing on it. Yes, expected. The point of having 'int fred = ...' is to emphasize the distinction between gcc and clang considering the pair of invocations foo(0) and foo(0). >> Incidentally, trying to define an analogous pair of overloaded >> functions simply rejects the definition with a negative value for >> the extent of the array parameter. That holds for both gcc and >> clang. > > Yes, in ordinary functions, as opposed to function templates, GCC does > not ignore any issues with array sizes in parameter declarations, > which is the reason I specifically mentioned that the issue is only > visible in template context. I didn't really think any of my reporting would surprise you. I included everything in the interest of completeness and to illustrate my thought processes. After seeing your reply I tried one more test, changing the first template to template void foo(int (*p)[T::N]) { std::cout << "array of size " << sizeof *p << std::endl; } in which case the invocation foo(0); produces '...' under both gcc and clang.