Bug 7033 - [3.3/3.4 regression] Partial template specializations accepted even if a template parameter is used in a non-deduced context
Summary: [3.3/3.4 regression] Partial template specializations accepted even if a temp...
Status: RESOLVED DUPLICATE of bug 13640
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.1
: P3 normal
Target Milestone: 3.3.1
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2002-06-14 09:06 UTC by Theodore.Papadopoulo
Modified: 2004-01-17 04:22 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2003-05-03 00:00:00


Attachments
Bug.C (517 bytes, application/octet-stream)
2003-05-21 15:16 UTC, Theodore.Papadopoulo
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Theodore.Papadopoulo 2002-06-14 09:06:01 UTC
In the code below, the specilizations with the comments mentionning "extended iterators" does not work. The compiler seems to not consider the last couple of specialization (without any warning or error message at this point) and insists on using the general definition for SameIteratorAs (the one providing the void argument).

I do believe that the standard allows the construct given in the example, so I think this is the g++ frontend fault. The output from g++-3.1, g++-3.0 and g++-2.95.3 are:

mururoa->/usr/local/gcc-3.1/bin/g++ Bug.C 
Bug.C: In function `int main()':
Bug.C:62: variable or field `i3' declared void
Bug.C:63: request for member `print' in `i3', which is of non-aggregate type `
   int'

mururoa->/usr/local/gcc-3.0/bin/g++ Bug.C
Bug.C: In function `int main()':
Bug.C:62: variable or field `i3' declared void
Bug.C:63: request for member `print' in `i3', which is of non-aggregate type 
   `int' 
  
mururoa->/usr/local/gcc/bin/g++ Bug.C  # 2.95.3
Bug.C:25: template parameters not used in partial specialization:
Bug.C:25:         `type'
Bug.C: In function `int main()':
Bug.C:62: variable or field `i3' declared void
Bug.C:63: request for member `print' in `i3', which is of non-aggregate type `int'

Release:
g++-3.1

Environment:
Frontend bug not related to environment IMHO, but in any case
this is a redhat 6.1 system with an upgraded kernel 2.4.17 (and also an upgraded libc).

How-To-Repeat:
Just compile the program above with g++-3.1.
Comment 1 Theodore.Papadopoulo 2002-06-14 09:06:01 UTC
Fix:
None very clean.... Specific cases for given "type" can be done.
Comment 2 Kriang Lerdsuwanakij 2002-06-14 09:56:49 UTC
State-Changed-From-To: open->analyzed
State-Changed-Why: Confirmed.
Comment 3 Wolfgang Bangerth 2003-01-22 20:55:33 UTC
From: Wolfgang Bangerth <bangerth@ticam.utexas.edu>
To: gcc-bugs@gcc.gnu.org, <gcc-gnats@gcc.gnu.org>
Cc: Theodore.Papadopoulo@sophia.inria.fr, <Lionel.Champalaune@sophia.inria.fr>
Subject: Re: c++/7033: [2003-01-22] Matching of template patterns
Date: Wed, 22 Jan 2003 20:55:33 -0600 (CST)

 This report can be reduced to the following snippet: 
 ------------------------------
 template <typename, typename> struct S;
 
 template <template <typename> class C,
           typename T,
           typename V>
 struct S<C<T>,typename C<T>::template it<V> > {
     typedef int it;
 };
 
 
 template <typename> struct U {
     template <typename> struct it {
         it (int);
     };
 };
 
 int main() {
   typedef U<int>   c2i;
   S<c2i,c2i::it<int> >::it it;
 };
 -------------------------------
 
 The question is: will the template list in the last line match the 
 specialization of S or not. gcc says "no" and complains about the 
 incomplete general template S when creating the variable.
 
 FWIW, icc agrees with gcc here. I have no opinion.
 
 W.
 
 -------------------------------------------------------------------------
 Wolfgang Bangerth             email:            bangerth@ticam.utexas.edu
                               www: http://www.ticam.utexas.edu/~bangerth/
 
 

Comment 4 Giovanni Bajo 2003-05-05 13:20:01 UTC
From: "Giovanni Bajo" <giovannibajo@libero.it>
To: <gcc-gnats@gcc.gnu.org>,
	<Theodore.Papadopoulo@sophia.inria.fr>,
	<gcc-bugs@gcc.gnu.org>,
	<nobody@gcc.gnu.org>,
	<gcc-prs@gcc.gnu.org>,
	<Lionel.Champalaune@sophia.inria.fr>
Cc:  
Subject: Re: c++/7033: [3.3/3.4 regression] [2003-05-30] Partial template specializations accepted even if a template parameter is used in a non-deduced context
Date: Mon, 5 May 2003 13:20:01 +0200

 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=7033
 
 The specialization should not be selected because §14.8.2.4p4 clearly
 specifies that A<T>::B<Q> is a non-deduced context for both T and Q.
 
 But there's more: I'm confident that defining a partial template
 specialization whose arguments can't be fully deduced from the arguments of
 the original template is ill-formed. In fact, GCC correctly rejects this:
 
 -----------------------------------------------
 template <class> struct K;
 
 template <class T>
 struct K<int> {};
 -----------------------------------------------
 pr7033.cpp:4: error: template parameters not used in partial specialization:
 pr7033.cpp:4: error:         `T'
 
 but it fails to reject this:
 
 -----------------------------------------------
 template <typename, typename> struct S;
 
 template <template <typename> class C,
 typename T,
 typename V>
 struct S<C<T>,typename C<T>::template it<V> > {};
 -----------------------------------------------
 
 which is currently accepted by 3.3 and 3.4, even if "V" is used only in
 non-deduced contexts. This is a regression (rechecked on CVS 20050305 for
 both 3.3 and 3.4) with respect to 2.95 which was rejecting the code:
 
 pr7033.cpp:6: template parameters not used in partial specialization:
 pr7033.cpp:6:         `V'
 
 (actually, the error message could be "template parameter used in
 non-decuded context", but anyway).
 
 This is a reject-legal regression, and I now flagged it as such.
 
 Giovanni Bajo
 

Comment 5 Giovanni Bajo 2003-05-05 13:27:41 UTC
From: "Giovanni Bajo" <giovannibajo@libero.it>
To: <gcc-gnats@gcc.gnu.org>,
	<Theodore.Papadopoulo@sophia.inria.fr>,
	<gcc-bugs@gcc.gnu.org>,
	<nobody@gcc.gnu.org>,
	<gcc-prs@gcc.gnu.org>,
	<Lionel.Champalaune@sophia.inria.fr>
Cc:  
Subject: Re: c++/7033: [3.3/3.4 regression] [2003-05-30] Partial template specializations accepted even if a template parameter is used in a non-deduced context
Date: Mon, 5 May 2003 13:27:41 +0200

 http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=7033
 
 Sorry for the confusion, I meant "this is an accept-illegal regression" of
 course.
 
 Giovanni Bajo
 

Comment 6 Theodore.Papadopoulo 2003-05-06 20:34:40 UTC
From: Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>
To: "Giovanni Bajo" <giovannibajo@libero.it>
Cc: gcc-gnats@gcc.gnu.org, gcc-bugs@gcc.gnu.org, nobody@gcc.gnu.org,
   gcc-prs@gcc.gnu.org, Lionel.Champalaune@sophia.inria.fr,
   Gabriel DOS_REIS <Gabriel.Dos_Reis@sophia.inria.fr>
Subject: Re: c++/7033: [3.3/3.4 regression] [2003-05-30] Partial template specializations accepted even if a template parameter is used in a non-deduced context 
Date: Tue, 06 May 2003 20:34:40 +0200

 giovannibajo@libero.it said:
 > http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=7033
 
 > The specialization should not be selected because §14.8.2.4p4 clearly
 > specifies that A<T>::B<Q> is a non-deduced context for both T and Q.
 
 > But there's more: I'm confident that defining a partial template
 > specialization whose arguments can't be fully deduced from the
 > arguments of the original template is ill-formed.
 
 I kindly disagree.
 
 First §14.8.2.4p4 deals with "Function template specializations" not 
 with "Class template specializations". The program might be invalid 
 but not for this reason.
 
 Second, the specialization can fully be deduced from the template 
 arguments (look again), so that your second affirmation is equally 
 wrong. Both T and V are given in the instanciation.
 
 Actually, looking at the standard with Gaby today, it looks like that 
 by  §14.5.4.1p1, the unique specialization exactly matched by all the 
 template parameters (which is the case here) should be selected....
 
 I do not definitely claim that the example should compile because I 
 do not know all the arcanes of the standard with this respect, but I 
 have not yet seen an argument that forbids it. And moreover, 
 forbidding this would be extremely surprising for the users without a 
 proper message explaining the reasons for that...
 
 
 --------------------------------------------------------------------
 Theodore Papadopoulo
 Email: Theodore.Papadopoulo@sophia.inria.fr Tel: (33) 04 92 38 76 01
  --------------------------------------------------------------------
 
 

Comment 7 Giovanni Bajo 2003-05-07 01:46:12 UTC
From: "Giovanni Bajo" <giovannibajo@libero.it>
To: "Theodore Papadopoulo" <Theodore.Papadopoulo@sophia.inria.fr>
Cc: <gcc-gnats@gcc.gnu.org>,
	<gcc-bugs@gcc.gnu.org>,
	<nobody@gcc.gnu.org>,
	<gcc-prs@gcc.gnu.org>,
	<Lionel.Champalaune@sophia.inria.fr>,
	"Gabriel DOS_REIS" <Gabriel.Dos_Reis@sophia.inria.fr>
Subject: Re: c++/7033: [3.3/3.4 regression] [2003-05-30] Partial template specializations accepted even if a template parameter is used in a non-deduced context 
Date: Wed, 7 May 2003 01:46:12 +0200

 Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr> wrote:
 
 > First §14.8.2.4p4 deals with "Function template specializations" not
 > with "Class template specializations". The program might be invalid
 > but not for this reason.
 
 Sure, but the deduction rules are exactly the same. It's clearly stated in
 §14.5.4.1p2 [temp.class.spec.match]: "A partial specialization matches a
 given actual template argument list if the template arguments of the partial
 specialization can be deduced from the actual template argument list
 (14.8.2)".
 
 Note that it refers _exactly_ to §14.8.2 as The Way to match a partial
 specialization. In fact, §14.8.2.4 is called "Deducing template arguments
 from a type", and §14.8.2 is "Template argument decuction". Those are _the_
 rules to deduce template arguments, either to deduce arguments for a
 function template call, or to match a partial specialization.
 
 > Second, the specialization can fully be deduced from the template
 > arguments (look again), so that your second affirmation is equally
 > wrong. Both T and V are given in the instanciation.
 
 No. You don't specify T and V in the instanciation. Let's look at it again:
 
 ---------------------------
 template <typename A, typename B> struct S;
 
 template <template <typename> class C,
            typename T,
            typename V>
  struct S<C<T>,typename C<T>::template it<V> >
 {
    [...]
 };
 
 template <typename> struct U {
      template <typename> struct it {
          it (int);
      };
  };
 
 typedef U<int>   c2i;
 S<c2i,  c2i::it<int> >::it it;
 ---------------------------
 
 You're specifiying two template parameters. These two template parameters
 are obviously the template parameters for the primary template, so we now
 know that [A = U<int>] and [B = U<int>::it<int>]. Now, the whole point is:
 is it possible to deduce C, T, V from these A,B? §14.8.2 is the arbiter here
 because it's where the deduction rules are specified.
 
 The first step is to deduce C<T> from [A = U<int>]. This is a easy, because
 [C = U] and [T = int]. This deduction succeeds because it's allowed
 _explicitally_ by §14.8.2.4p9, which says that TT<T> (for any
 template-template parameter TT and type T) is a deducible form (among
 others).
 
 The second step would be to deduce C<T>::it<V> from [B = U<int>::it<int>].
 Since C and T have been already deduced, the compiler will try deducing
 U<int>::it<V> from [B = U<int>::it<int>]. Now, I understand that here one
 could say "hey, it's easy, U=int and we're done", but this is not what the
 standard says. First, if you look into §14.8.2.4p9, such a format (inner
 template within a class) is not listed among the deducible forms. And if
 this was not enough, we still have §14.8.2.4p4, which says:
 
 "The non-deduced contexts are:
 [...]
 - The nested-name-specifier of a type what was specified using a
 qualified-id".
 
 There is also an example: "If a type is specified as A<T>::B<T2>, both T and
 T2 are non-deduced". And isn't this _exactly_ our case?
 
 This means that the compiler _cannot_ deduce V in U<int>::it<V> from [B =
 U<int>::it<int>]. Which means that deduction fails for the partial
 specialization, and the primary template is instanciated.
 
 I agree this might look strange at first sight, but this is exactly how
 deduction works. Inner templates make deduction fails, always. Even if it
 was simply "A<T>::B", deduction for T would fail (it's listed as another
 example in the same paragraph).
 
 > Actually, looking at the standard with Gaby today, it looks like that
 > by  §14.5.4.1p1, the unique specialization exactly matched by all the
 > template parameters (which is the case here) should be selected....
 
 §14.5.4.1p1 only says that if there is a single matching specialization, the
 instantion is generated for that specialization, otherwise partial ordering
 kicks in. My point is that your instanciation does _NOT_ match that partial
 specialization, so the instantiation must be generated from the primary
 template.
 
 > I do not definitely claim that the example should compile because I
 > do not know all the arcanes of the standard with this respect, but I
 > have not yet seen an argument that forbids it. And moreover,
 > forbidding this would be extremely surprising for the users without a
 > proper message explaining the reasons for that...
 
 In fact, what the compiler should do is to reject the partial specialization
 itself when it's defined, because it's ill-formed (it could never be matched
 since V appears only in a non-deduced context). An error message like
 "partial specialization is invalid because template parameter V appears only
 in a non-deduced context" might be clear enough.
 
 Giovanni Bajo
Comment 8 Mark Mitchell 2003-06-11 22:15:56 UTC
Giovanni is correct; the nested-name-specified is a non-deduced context.

Note that partial specialization matching is defined in terms of function
template deduction (see [temp.class.order]).
Comment 9 Giovanni Bajo 2003-06-11 22:58:58 UTC
Mark,

should I file a new enhancement PR about adding a diagnostic message if the 
code defines a partial specialization which could never be chosen because it 
relies on non-deduced contexts? I think it would be a valuable feature. 
Comment 10 Giovanni Bajo 2004-01-10 20:09:22 UTC
reopening this ...
Comment 11 Giovanni Bajo 2004-01-10 20:10:12 UTC
... to flag it as a duplicate of PR13640, which contains the regression about 
the missing diagnostic for the useless specialization.

*** This bug has been marked as a duplicate of 13640 ***