To the best of my knowledge here's what's going on.
DR228 says:
[Voted into WP at April 2003 meeting.]
Consider the following example:
template<class T>
struct X {
virtual void f();
};
template<class T>
struct Y {
void g(X<T> *p) {
p->template X<T>::f();
}
};
This is an error because X is not a member template; 14.2 [temp.names] paragraph 5 says:
If a name prefixed by the keyword template is not the name of a member template, the program is ill-formed.
In a way this makes perfect sense: X is found to be a template using ordinary lookup even though p has a dependent type. However, I think this makes the use of the template prefix even harder to teach.
Was this intentionally outlawed?
Proposed Resolution (4/02):
Elide the first use of the word "member" in 14.2 [temp.names] paragraph 5 so that its first sentence reads:
If a name prefixed by the keyword template is not the name of a template, the program is ill-formed.
However, in the most current publicly available draft of the C++ standard N4296 the following wording appears in §14.2.5:
A name prefixed by the keyword template shall be a template-id or the name shall refer to a class template. [Note: The keyword template
may not be applied to non-template members of class templates. —end note] [Note: As is the case with the typename
prefix, the template
prefix is allowed in cases where it is not strictly necessary; i.e., when the nested-name-specifier or the expression on the left of the ->
or .
is not dependent on a template-parameter, or the use does not appear in the scope of a template. —end note]
[Example:
template <class T> struct A {
void f(int);
template <class U> void f(U);
};
template <class T> void f(T t) {
A<T> a;
a.template f<>(t); // OK: calls template
a.template f(t); // error: not a template-id
}
template <class T> struct B {
template <class T2> struct C { };
};
// OK: T::template C names a class template:
template <class T, template <class X> class TT = T::template C> struct D { };
D<B<int> > db;
—end example]
This wording sounded similar, but different enough to go digging. I found that in the N3126 draft the wording was changed to this version.
I was able to link this change back to this DR96:
The following is the wording from 14.2 [temp.names] paragraphs 4 and 5 that discusses the use of the "template" keyword following . or -> and in qualified names.
{snip}
The whole point of this feature is to say that the "template" keyword is needed to indicate that a "<" begins a template parameter list in certain contexts. The constraints in paragraph 5 leave open to debate certain cases.
First, I think it should be made more clear that the template name must be followed by a template argument list when the "template" keyword is used in these contexts. If we don't make this clear, we would have to add several semantic clarifications instead. For example, if you say "p->template f()", and "f" is an overload set containing both templates and nontemplates: a) is this valid? b) are the nontemplates in the overload set ignored? If the user is forced to write "p->template f<>()" it is clear that this is valid, and it is equally clear that nontemplates in the overload set are ignored. As this feature was added purely to provide syntactic guidance, I think it is important that it otherwise have no semantic implications.
Essentially, the very subtle change of DR228 was lost during a subsequent revision; however, because no similar restriction was placed the intent of DR228 probably still holds unless there's been another revision in the standard. This means that template lookup has to occur globally in this case, even though it's a dependent type.
Let's look at our name lookup rules §3.4.5.1:
In a class member access expression (5.2.5), if the .
or ->
token is immediately followed by an identifier followed by a <
, the identifier must be looked up to determine whether the <
is the beginning of a template argument list (14.2) or a less-than operator. The identifier is first looked up in the class of the object expression. If the identifier is not found, it is then looked up in the context of the entire postfix-expression and shall name a class template.
This seems to explicitly state that in baz.foo->template bar<T>();
We will first look in the class context, this includes standard template lookup. After that is done and if nothing is found, if the form of the expression is correct we jump to the context of the entire expression. In essence, it has been promoted and the lookup for that name must perform the same way if the line just read template bar<T>();
Really though we already knew this from DR228. I just wanted to double check and confirm. The real question is which template ought to get priority, the one in the global scope or the one in the class scope.
For that we now need to ask unqualified name lookup, because now bar is being considered in the same context as foo, so it's no longer following member lookup rules, it's following normal, unqualified template lookup rules, which, naturally, prefer the local version.
So in summation, it seems that Clang and MSVC exhibit correct behavior, and GCC and EDG do not in this instance.
My best guess as to why GCC has it wrong is choosing the wrong context to assign to the expression after the rule is triggered. Instead of placing the context at the same level as the postfix-expression it may be just placing it at in the global level on accident? Maybe it simply skips the first lookup step? (But this is merely speculation, I'd have to actually figure out where to look in the GCC source to say.) This would also explain why @Mikael Persson's solution of changing the lookup to a qualified one caused the compile to start again.
The linked bug report from the asker has people talking about why the global scope must be considered, and it ought to be, but it seems pretty straight forward that a local scope match must be given higher priority than the global one. It also seems like there's been a bit of activity there recently.
i.Inner::template hi<T>();
. But that doesn't really explain why this doesn't work, and I think it should work. Maybe file a bug report with GCC and see what they think of it. – Funktemplate
keyword, thoughInner
is clearly a dependent type according to [temp.dep.type]/(8.3) (and thetemplate
keyword is required through [temp.dep.expr]/(3.1) and [temp.names]/4). – Synchronoustemplate
). It would be nice if all the compilers agreed though, of course. – Mantlinghi
andbye
. BecauseFoo
itself is a class template, the name lookup for theInner
member function templatehi
and member functionbye
are done at the point of instantiation. Somehow, gcc and clang resolve this differently. ` [basic.lookup.unqual]/3` has something to say about different syntactic forms and name lookup, but not in the same context as your code. You'd best submit a DR to gcc. – Ferventtemplate
keyword. The name lookup for this code is rather intricate and I'm not sure which compiler gets it right (though my money would be on clang). – FerventInner
is "— a nested class or enumeration that is a member of the current instantiation," ([temp.dep.type]/(8.3)), thus a dependent type. Soi
is "an identifier associated by name lookup with one or more declarations declared with a dependent type, " ([temp.dep.expr]/(3.1)) – SynchronousInner
can be explicitly specialized later, can't it? – Synchronoushi
after structFoo
definition. – Pyxidium