This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]