This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
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
- From: "Giovanni Bajo" <giovannibajo at libero dot it>
- To: "Theodore Papadopoulo" <Theodore dot Papadopoulo at sophia dot inria dot fr>
- Cc: <gcc-gnats at gcc dot gnu dot org>,<gcc-bugs at gcc dot gnu dot org>,<nobody at gcc dot gnu dot org>,<gcc-prs at gcc dot gnu dot org>,<Lionel dot Champalaune at sophia dot inria dot fr>,"Gabriel DOS_REIS" <Gabriel dot Dos_Reis at sophia dot inria dot fr>
- Date: Wed, 7 May 2003 01:46:12 +0200
- 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
- References: <200305061834.h46IYeKM025998@mururoa.inria.fr>
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