Bug 27403 - T() can be an integer constant but is rejected as not one
Summary: T() can be an integer constant but is rejected as not one
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks: 51312
  Show dependency treegraph
 
Reported: 2006-05-02 21:12 UTC by Andrew Pinski
Modified: 2013-01-19 14:22 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Pinski 2006-05-02 21:12:26 UTC
Testcase:

template <int> struct A { typedef int I; };

template <class T>
typename A<T()  >::I foo (T) { return 0; }

-----
I found this while looking at PR 27402.  This is not a regression as it did not work in 2.95 on wards.
Comment 1 Wolfgang Bangerth 2006-05-26 15:26:03 UTC
gcc parses this as

template <class T>
typename A<T (&)()  >::I foo (T) { return 0; }

i.e. as meaning that the argument is not an integer, but a function that
returns an integer.

A simpler testcase is this (icc accepts it, though I'm not sure who's right):
-------------------
template <int> struct A {};
A<int()> foo (int);
-------------------

W.
Comment 2 Andrew Pinski 2012-02-08 20:16:38 UTC
t4.cc:4:17: error: type/value mismatch at argument 1 in template parameter list for ‘template<int <anonymous> > struct A’
t4.cc:4:17: error:   expected a constant of type ‘int’, got ‘T()’
Comment 3 Jonathan Wakely 2013-01-19 14:22:55 UTC
Wolfgang is right, the testcase is invalid, T() is parsed as a function type, not an expression that value-initializes a T.

[temp.arg]p2, "In a template-argument, an ambiguity between a type-id and an expression is resolved to a type-id, regardless of the form of the corresponding template-parameter."

i.e. it doesn't matter that the argument is expecting a non-type parameter of type int, because T() can be a type-id it is interpreted as one.

(This happened to be discussed last month on the committee reflectors)

Using T{} in C++11 works because that cannot be a type-id and is unambiguously an initialization of T.