[temp.deduct.type] paragraph 8 lists all deduced contexts, but it seems not to include template-name
<TT>
where template-name
refers to a class template and TT
refers to a template template argument. Is this a deduced context?
If it is, why?
If not, consider the following code:
template<template<typename> class U, template<typename> class V>
struct foo {};
template<template<typename> class U>
struct foo<U, U> {};
int main() {}
This code compiles under Clang 7.0.0 and GCC 8.0.1, which means the compilers consider the partial specialization is more specialized than the primary template, which means U
and V
in the primary template are successfully deduced against foo<U, U>
. Is this a compiler bug?
This paragraph is full of problems, including the one you pointed out. Core issue 2328 has a nice list:
The presentation style of 17.9.2.5 [temp.deduct.type] paragraph 8
results in a specification that is unclear, needlessly verbose, and
incomplete. Specific problems include:
What does it mean for P
and A
to have one of a set of forms? Do they both have to have that form? (That doesn't happen; typically,
only P
contains template parameters)
In the introductory sentence, aren't T
, TT
, and i
supposed to be the names of template parameters rather than template arguments?
In T[i]
, it appears we can deduce i
, but not T
(T
can only be deduced in the form T[integer-constant]
)
What is an integer-constant
supposed to be?
What is a cv-list
?
Why can we not deduce const T
from T
? (Apparently you only get to deduce if both or neither type have a cv-list
, whatever a
cv-list
is.)
We have extreme redundancy because, for instance, there is no way to say “in T (T::*)(T)
, you can deduce any of those T
s, and it's OK
if some of the positions don't have a T
”. So we have seven (!) forms
of that construct, for all cases except the one where none of the
three positions contain a T
.
We have special case rules for pointers to member functions, even though they're not a special case and should be covered by the rule
for pointers to members and the rule for functions.
We do not allow deducing a template template parameter's value from a template template argument — there is a TT<T>
form, a TT<i>
form, a template-name<T>
form, and a
template-name<i>
form, but no TT<TT>
form
nor template-name<TT>
form.
It looks like the editor managed to get rid of cv-list
, at least, since the issue was filed. It's now just cv
. (cv-list
is kind of hilariously wrong, because [syntax] says that the -list suffix is for comma-separated lists...)
It's correct, template-name<TT>
is not a deduced context. That's not relevant here. Plain TT
is a deduced context, and that's what you have here
The deduced context template-name<I>
for a non-type template parameter I
means that you can deduce 5
when you have argument Foo<5>
to parameter Foo<I>
.
The reason template-name<TT>
is not a deduced context is fairly simple. If template-name<TT>
would be legal, then template-name
would have to take a template template parameter. That means it itself would have to be a template template template ("TTT"). There's only so much recursion in the language definition.
[edit]
In your example, you are deducing V
for U
to see if it's a specialization. Both are template templates. You are not trying to deduce whether Foo<U> is
Foo. Therefore your deduced context is
TT, not
template-name.`.
To answer point 2 of the comment, TT
is a deduced context because that form is listed explicitly. And what template-name<TT>
means is that TT
would have to be deducable when TT
is used as an argument to a known template. But what type of template accepts a template template parameter? That the hypothetical TTT
.