Bug 49051 - [Core/1322] Doesn't SFINAE away an invalid substitution into toplevel parameter type "T[N]"
Summary: [Core/1322] Doesn't SFINAE away an invalid substitution into toplevel paramet...
Status: SUSPENDED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-05-18 19:53 UTC by Johannes Schaub
Modified: 2022-01-09 05:40 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-01-06 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Johannes Schaub 2011-05-18 19:53:24 UTC
GCC incorrectly fails to compile this code

template<typename T> void f(T[1]) = delete; 
template<typename T> void f(...); 
int main() { f<void>(0); }

The substitution into "T" should fail, because "T[1]" is an invalid type, and
hence the call should use the second template. 

Note that I think it's unspecified in the spec what happens when we tweak
things as follows

template<typename T> void f(T[1]) = delete; 
template<typename T> void f(T*);
template<typename T> void f(...); 
int main() { f<void>(0); }

The first two templates are equivalent, but behave different during
substitution. The spec doesn't specify what the outcome of this is, I think.
Comment 1 Jason Merrill 2011-05-19 16:05:05 UTC
I disagree.  The transformation of array to pointer is done immediately at declaration time (8.3.5/6), so there is no substitution into an array type.  In resolving issue 1001, core agreed that the transformations in 8.3.5/6 are done at template definition time, not deferred until the instantiation.

http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1001
http://wiki.dinkumware.com/twiki/bin/view/Wg21batavia/CoreWorkingGroup#Core_issue_1001_Parameter_type_a
Comment 2 Johannes Schaub 2011-05-19 16:26:30 UTC
(In reply to comment #1)
> I disagree.  The transformation of array to pointer is done immediately at
> declaration time (8.3.5/6), so there is no substitution into an array type.  In
> resolving issue 1001, core agreed that the transformations in 8.3.5/6 are done
> at template definition time, not deferred until the instantiation.
> 
> http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1001
> http://wiki.dinkumware.com/twiki/bin/view/Wg21batavia/CoreWorkingGroup#Core_issue_1001_Parameter_type_a

jason, the transformation is immediately done at declaration time. I agree: That's why these two are equivalent:

    template<typename T> void f(T[1]);
    template<typename T> void f(T*);

For equivalence, both shall have identical parameter-type-lists, which these have. But before argument deduction, explicit template arguments are substituted, and those explicit arguments are substituted into the *unadjusted* parameter type. See 14.8.2p3 (FDIS):

"After this substitution is performed, the function parameter type adjustments described in 8.3.5 are performed."

The note that contains a list of substitution failures also has an example like that at 14.8.2p8:

   template <class T> int f(T[5]);
   int I = f<int>(0);
   int j = f<void>(0); // invalid array
Comment 3 Johannes Schaub 2011-05-19 16:56:07 UTC
(In reply to comment #2)
> (In reply to comment #1)
> > I disagree.  The transformation of array to pointer is done immediately at
> > declaration time (8.3.5/6), so there is no substitution into an array type.  In
> > resolving issue 1001, core agreed that the transformations in 8.3.5/6 are done
> > at template definition time, not deferred until the instantiation.
> > 
> > http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1001
> > http://wiki.dinkumware.com/twiki/bin/view/Wg21batavia/CoreWorkingGroup#Core_issue_1001_Parameter_type_a
> 
> jason, the transformation is immediately done at declaration time. I agree:
> That's why these two are equivalent:
> 
>     template<typename T> void f(T[1]);
>     template<typename T> void f(T*);
> 
> For equivalence, both shall have identical parameter-type-lists, which these
> have. But before argument deduction, explicit template arguments are
> substituted, and those explicit arguments are substituted into the *unadjusted*
> parameter type. See 14.8.2p3 (FDIS):
> 
> "After this substitution is performed, the function parameter type adjustments
> described in 8.3.5 are performed."
> 
> The note that contains a list of substitution failures also has an example like
> that at 14.8.2p8:
> 
>    template <class T> int f(T[5]);
>    int I = f<int>(0);
>    int j = f<void>(0); // invalid array

Ah I see now: The substitution for explicit arguments uses the *function type*, not the parameter types (according to p6). So in the example above, it uses "T*" and becomes "void*". It doesn't use "T[5]". p3 only applies when the dependent type was adjusted and substitution made it a non-adjusted type.

So on a second read of this, I agree to you. The note at 14.8.2p8 and the example of p3 were confusing me, both tricking me into thinking that for substitution, the parameter types themselves somehow would be used.
Comment 4 Jason Merrill 2011-05-19 17:20:44 UTC
Hmm, the example in 14.8.2p8 does seem to contradict my interpretation of the normative wording.  I'll raise this with core.
Comment 5 Johannes Schaub 2011-06-26 13:40:34 UTC
(In reply to comment #4)
> Hmm, the example in 14.8.2p8 does seem to contradict my interpretation of the
> normative wording.  I'll raise this with core.

A related question, if in the end we in fact don't SFINAE or error out with "T[N]" is, whether substitution for "N" is done at all. Because the type would be "T*", not "T[N]" anymore. 

    template<typename T>
    void f(char[T::size]);

    int main() { f<int>(); }

Does the substitution succeed?
Comment 6 Jason Merrill 2011-08-30 21:56:42 UTC
This will eventually be issue 1322,

  http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#1322

but the issues list hasn't been updated yet.  In Bloomington we assigned it priority 1 but didn't get to discussing it.