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.