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.
Fix: None very clean.... Specific cases for given "type" can be done.
State-Changed-From-To: open->analyzed State-Changed-Why: Confirmed.
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/
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
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
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 --------------------------------------------------------------------
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
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]).
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.
reopening this ...
... 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 ***