Skip to content

[temp.param] Add wording to clarify if conflicting type while template argument deduction takes place #905

@ranaanoop

Description

@ranaanoop

Full name of submitter: Anoop Rana

Reference (section label): temp.param

Link to reflector thread (if any): https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125300

Issue description: Consider the following program that shows implementation divergence. GCC and EDG accept the program while Clang and MSVC reject it. This seems ill-formed to me for the reason(s) given below. I reported the bug at gcc where the maintainer seems to say that there may be a defect here in the standard.

//----------------------v--->i named the parameter for explanation purposes
template <typename T, T p>
struct A { };

template <typename T, T t>
void f(A<T, t>) {
}

int main() {
    f(A<const int, 0>{});
}

Here is my explaination of why this ought to be ill-formed.

Step 1

Here we consider what happens for the expression A<const int, 0>{}.

From temp.param#5:

The top-level cv-qualifiers on the template-parameter are ignored when determining its type.

On the first glance it seems that when applied to the given snippet, the non-type template parameter named p should be int instead of const int.

But note the emphasis on the highlighted part in the above quoted statement. In particular, my interpretation of this(the phrase "when determining") is that the top-level cv-qualifiers are dropped when deducing the template parameter and so not when the template arguments are explicitly specified.

And since in my given snippet, we are explicitly specifying the template argument, there is no template argument deduction(TAD) here. Thus, the dropping of the top-level cv-qualifiers due to the above quoted temp.param#5 does not happen. Meaning the type of p is const int instead of int.

Note that i may be wrong in interpreting [temp.param#5] above.


But before further analysis, from temp.param#6:

A non-type non-reference template-parameter is a prvalue. It shall not be assigned to or in any other way have its value changed.

Moreover, from expr#6:

If a prvalue initially has the type “cv T”, where T is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.

When applying temp.param#6 and expr#6 to the given snippet, it means that p(a prvalue) will finally be of type int instead of const int.

Thus, the non-type template parameter p is of type int.

Step 2

Next, we consider what happens for the call expression f(A<const int, 0>{}).

Now currently we have a prvalue A<const int, 0> whose first type parameter T is const int while the second non-type template parameter p is of type int. Thus, for the function template f<> the first template type parameter T is deduced to be const int while the type of non-type template parameter t is deduced to be int. Thus there is a conflict between the type of T and hence the mentioned error saying:

<source>:7:6: note: candidate template ignored: deduced conflicting types for parameter 'T' ('const int' vs. 'int')
void f(A<T, t>) {
     ^

So, kindly clarify what is the intended behavior here and ammend the wording accordingly(if necessary) so that gcc etc can correct their compiler as currently they're not sure what is the problem here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions