cplusplus / CWG

Core Working Group
23 stars 7 forks source link

[temp.names] Current wording doesn't allow for deduction of template parameter when a name prefixed with template is not followed by template argument list <> #488

Closed ranaanoop closed 5 months ago

ranaanoop commented 5 months ago

Full name of submitter: Anoop Rana

Reference (section label): [temp.names]

Issue description: The current wording doesn't seem to allow c.template func(5) in the below shown program. We see implementation divergence here.

template<typename T>
struct C
{
     template<typename U> void func(U)
     {

     }
};
int main()
{
    C<int> c;  
    c.template func(5); //this is invalid as per current wording gcc and clang accepts but msvc rejects     
    //c.template func<>(5); //valid as per current wording. All compilers accepts this
}

The current wording in temp.names states:

A name prefixed by the keyword template shall be followed by a template argument list or refer to a class template or an alias template.

Suggestion Resolution

temp.names could be changed to:

A name prefixed by the keyword template shall be followed by a template argument list(If all of the template arguments can be deduced or obtained from default template arguments, the template argument list may be omitted) or refer to a class template or an alias template.

frederick-vs-ja commented 5 months ago

I think this is just a bug of MSVC and the standard wording looks fine.

ranaanoop commented 5 months ago

I think this is just a bug of MSVC and the standard wording looks fine.

@frederick-vs-ja There was a similar defect/gap in the standard wording CWG2608 Allowing ommiting empty template argument list for default arguments. I think here also, there is gap/defect in the wording very similar to that.

Also I don't think this is msvc issue because it starts accepting the code if you add an empty argument list <> See demo https://godbolt.org/z/Yrj94haa4:

template<typename T>
struct C
{
     template<typename U> void func(U)
     {

     }
};
int main()
{
    C<int> c;  
    c.template func(5); //this is invalid as per current wording gcc and clang accepts but msvc rejects     
    //c.template func<>(5); //valid as per current wording. All compilers accepts this
}
ranaanoop commented 5 months ago

@frederick-vs-ja I don't think this is an msvc issue because msvc starts accepting the code if you specify an empty argument list <>. That is, this does seem like a wording defect in the standard.

template<typename T>
struct C
{
     template<typename U> void func(U)
     {

     }
};
int main()
{
    C<int> c;  
    c.template func(5); //this is invalid as per current wording gcc and clang accepts but msvc rejects     
    //c.template func<>(5); //valid as per current wording. All compilers accepts this including msvc
}
jensmaurer commented 5 months ago

The reason template exists in this syntactic position is to be able to differentiate the meaning of the token < between a less-than operator and the start of a template-argument-list. If there is no template-argument-list, template is not needed, and, as you correctly observed, in that case it's actually forbidden.

Please file bug reports against the affected vendors; the standard wording seems clear. This case is different from CWG2608, where syntactic disambiguation isn't in an issue.

In your particular example, c is non-dependent, so template isn't needed regardless of the presence of a template-argument-list (because the meaning of all names are known).

If you feel you want to make template optional (as opposed to forbidden) for the case above, feel free to write a paper with rationale, directed to EWG.