I have a problem with this code snippet:
template <typename T>
struct S
{
static int a;
};
template <typename T>
decltype(S<T>::a) S<T>::a;
clang-3.4 says:
s.cpp:8:25: error: redefinition of 'a' with a different type: 'decltype(S<T>::a)' vs 'int'
decltype(S<T>::a) S<T>::a;
^
s.cpp:4:14: note: previous definition is here
static int a;
^
1 error generated.
But gcc-4.8.2 accepts. Which of the compilers is right? Should I avoid such code in the future?
Clang is demanding that the definition match the declaration at template definition time, whereas GCC and others defer matching until instantiation time (which never even happens for your example).
Clang accepts this:
#include <type_traits>
template <typename T>
struct S
{
static int a;
};
template <typename T>
typename std::enable_if< true, int >::type S<T>::a; // Resolves before instantiation
but rejects this small change:
template <typename T>
typename std::enable_if< std::is_same< T, T >::value, int >::type S<T>::a;
I cannot recall where the standard dictates when object declaration matching occurs, but I suspect that Clang is within its rights to reject the code. The intent of the standard, if I recall correctly, is that each declaration matches exactly one definition, and that mapping may be determined before instantiation time.
With the looser rule that GCC is apparently applying, you could have two member declarations and two definitions, but each definition may finalize either of the declarations depending on the template parameters.
The code which GCC and MSVC are accepting is ill-formed, no diagnosis required… pending finding the actual standardese buried somewhere in §3 [basic], §7 [dcl.dcl], §8 [dcl.decl], §14 [temp], or maybe somewhere else.
I still cannot find what rule matches object definitions to preceding declarations, but §14.4/2 dictates that decltype(…) cannot be the equivalent (I assume in the declarative sense) to int.
If an expression e involves a template parameter, decltype(e)
denotes a unique dependent type. Two such decltype-specifiers refer
to the same type only if their expressions are equivalent (14.5.6.1).
[Note: however, it may be aliased, e.g., by a typedef-name. — end
note ]
I'm pretty sure that equivalence, not mere aliasing, is necessary for the definition to match the declaration. §14.5.6.1 delves pretty deep into this territory, except it is specifically discussing function signatures.
I think Clang might be right in rejecting this. 14.2p2 says about decltype(e)
If an expression e involves a template parameter, decltype(e) denotes a unique dependent type.
In DR #2, the discussion trace says
My opinion (which I think matches several posted on the reflector recently) is that the out-of-class definition must match the declaration in the template.
...
In general, if you can match the declarations up using only information from the template, then the declaration is valid.
I think it still matches if one of them uses a typedef (as demonstrated in the DR), because S<T>::type is a member of the current instantiation and the type aliased can be looked up directly. But a decltype(e), as specified above, will always denote a unique type (during template parse time) except with respect to another decltype(e) that specifies an equivalent expression.
Why did I say might? Because of 14.6p8
No diagnostic shall be issued for a template for which a valid specialization can be generated.
One could read this as saying the type equivalence check is simply delayed till after instantiation. This, however, would contradict the discussion trace in the DR I think, because they say "if you can match the declarations up using only information from the template, then the declaration is valid" (and I assume the author of this statement meant to be exhaustive about the situations when the declaration is valid).
For me clang is broken here.
All combinations with decltype will fail. Without decltype it works.
template <typename T>
struct S
{
static int a;
using type = decltype( a );
typedef decltype( a ) type2;
};
template <typename T>
1) decltype(S<T>::a) S<T>::a;
2) int S<T>::a;
3) typename S<T>::type S<T>::a;
4) typename S<T>::type2 S<T>::a;
1 gcc works, clang fails
2 gcc + clang works
3 gcc works, clang fails
4 gcc works, clang fails
I did some more tries to work around the problem, but could not have any success.
There are some more discussions on that kind of problems:
C++ Static member initalization (template fun inside)
Edit:
I found that this topic is simply "not resolved" in the standard until now and clang did not implemented it:
Take a look at:
http://clang.llvm.org/cxx_dr_status.html ( point 205 )
I hope that I did not misunderstood the page. Feel free to correct my interpretation.
Related
I have tried to construct a case that requires no typename or template, but still yield a variable or template depending on whether a given name t is a function parameter pack or not
template<typename T> struct A { template<int> static void f(int) { } };
template<typename...T> struct A<void(T...,...)> { static const int f = 0; };
template<typename> using type = int;
template<typename T> void f(T t) { A<void(type<decltype(t)>...)>::f<0>(1); }
int main() {
f(1);
}
The above will refer to the static const int, and do a comparison. The following just has T t changed to be a pack and make f refer to a template, but GCC does not like either
template<typename ...T> void f(T ...t) { A<void(type<decltype(t)>...)>::f<0>(1); }
int main() {
f(1, 2, 3);
}
GCC complains for the first
main.cpp:5:68: error: incomplete type 'A<void(type<decltype (t)>, ...)>' used in nested name specifier
template<typename T> void f(T t) { A<void(type<decltype(t)>...)>::f<0>(1); }
And for the second
main.cpp:5:74: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'
template<typename ...T> void f(T ...t) { A<void(type<decltype(t)>...)>::f<0>(1); }
I have multiple questions
Does the above code work according to the language, or is there an error?
Since Clang accepts both variants but GCC rejects, I wanted to ask what compiler is correct?
If I remove the body of the primary template, then for the f(1, 2, 3) case, Clang complains
main.cpp:5:42: error: implicit instantiation of undefined template 'A<void (int)>'
Please note that it says A<void (int) >, while I would expected A<void (int, int, int)>. How does this behavior occur? Is this a bug in my code - i.e is it illformed, or is it a bug in Clang? I seem to remember a defect report about the order of expansion vs the substitution of alias template, is that relevant and does it render my code ill-formed?
Expanding a parameter pack either should, or does, make an expression type dependent. Regardless of whether the things expanded are type dependent.
If it did not, there would be a gaping hole in the type dependency rules of C++ and it would be a defect in the standard.
So A<void(type<decltype(t)>...)>::f when t is a pack, no matter what tricks you pull in the void( here ) parts to unpack the t, should be a dependent type, and template is required before the f if it is a template.
In the case where t is not a pack, it is intended that type<decltype(t)> not be dependent (See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1390), but the standard may or may not agree at this point (I think not?)
If compilers did "what the committee intended", then when t is not a pack:
A<void(type<decltype(t)>...)>::f<0>(1)
could mean
A<void(int...)>::f<0>(1)
which is
A<void(int, ...)>::f<0>(1)
and if f is a template (your code makes it an int, but I think swapping the two should work) this would be fine. But the standard apparently currently disagrees?
So if http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1390 was implemented, then you could swap your two A specializations. The void(T...,...) specialization should have a template<int> void f(int), and the T specialization should have a static const int.
Now in the case where A<> is dependent (on the size of a pack), ::f is an int and does not need template. In the case where A<> is not dependent, ::f is a template but does not need disambiguation.
We can replace the type<decltype(t)>... with:
decltype(sizeof(decltype(t)*))...
and sizeof(decltype(t)*) is of non-dependent type (it is std::size_t), decltype gives us a std::size_t, and the ... is treated as a old-school ... arg. This means void(std::size_t...) becomes a non-dependent type, so A<void(std::size_t...)> is not dependent, so ::f being a template is not a template in a dependent context.
In the case where t is a parameter pack with one element
decltype(sizeof(decltype(t)*))...
becomes
std::size_t
but in a dependent context (one copy per element in t pack). So we get
A<void(std::size_t)>::f
which is presumed to be a scalar value, so
A<void(std::size_t)>::f<0>(1)
becomes an expression evaluating to false.
(Chain of logic generated in a discussion with Johannes in comments in original question).
Your second case is ill-formed; A<void(type<decltype(t)>...)>::f<0>(1) should be
A<void(type<decltype(t)>...)>::template f<0>(1)
// ~~~~~~~~~
For the first case, both compilers are behaving incorrectly; this was considered sufficiently confusing that CWG 1520 was raised to query the correct behavior; the conclusion was that pack expansion should be applied before alias substitution:
The latter interpretation (a list of specializations) is the correct interpretation; a parameter pack can't be substituted into anything, including an alias template specialization. CWG felt that this is clear enough in the current wording.
This is reminiscent of CWG 1558 (alias templates and SFINAE), which was fixed for C++14, but per the above even C++11 compilers are expected to get this correct, so it is disappointing that gcc and clang get it wrong (though in fairness they do behave correctly in simpler cases, including the motivating example in CWG 1520). Note that MSVC had a similar bug till recently; it is fixed in VS2015.
Your code (only in the first case) is correct; but as a workaround, you could alter your alias template to use and discard its template parameter, fixing your program for both compilers - of course that means that your CWG 1390 exploit will cease to be valid:
template<typename T> using type = decltype(((int(*)(T*))(0))(0)); // int
However, I don't think your CWG 1390 trick can work as presented, since even though the expansion-substitution of type<decltype(t)>... is not dependent on the types of t..., it is dependent on their number:
template<typename T> struct A { template<int> static void f(int) {} };
template<> struct A<void(int, int, int)> { static const int f = 0; };
As Yakk points out, it can be made to work if you swap the member function template and data member, since a data member is OK in dependent context.
This issue is based on section C++ reference : dependent name - The template disambiguator for dependent name.
I have understood when invoking the template member function in a template class, the keyword template is necessary to make the compiler know the following bracket is used for indicating template argument.just like the used example in this section.
template<typename T>
struct S {
template<typename U> void foo(){}
};
template<typename T>
void bar()
{
S<T> s;
s.foo<T>(); // error: < parsed as less than operator
s.template foo<T>(); // OK
}
However, in the consequent part it describes when a template name appears in a member access expression (after -> or after .), the disambiguator is unnecessary if there is a template with the same name found by ordinary lookup in the context of the expression..
Then it comes with the following code. Comparing with previous example it defines set function whose name exists in standard library as well. At the meanwhile, using std::set is set up to make set template visible in template function.
In this condition, even if keyword template is not provided it still works well.
#include <set>
using std::set; // makes 'set' visible to lookup from bar
template<typename T>
struct S {
template<typename U> void set(){}
};
template<typename T>
void bar()
{
S<T> s;
s.set<T>(); // not an error if ::set is visible:
// (and since C++11, this is well-formed)
s.template set<T>(); // works with and without ::set
}
Based on my understanding, I tried my own version
#include <iostream>
template <typename T>
struct S{
template <typename U> void func(){
std::cout << "In S::func\n";
}
};
// In order to make member template function is visible in function test,
// defining a global template function **func** whose name is same with one
// member template function in struct S.
template <typename M>
void func(){
std::cout << "from ordinary func\n";
}
template <typename M>
void test(){
S<M> s;
func<M>(); // test func template function is visible in test function
s.func<M>();
}
int main(){
test<int>();
}
The detail error message is listed as follows
[17:17:50][ryu#C++_test]$ g++ -g typename2.cpp
typename2.cpp:61:7: error: use 'template' keyword to treat 'func' as a dependent
template name
s.func<M>();
^
template
1 error generated.
Any advice is appreciated on how to make my own code works well without keyword template.
Short version
Don't rely on this. Use the template keyword as you're supposed to, don't try such an obscure hack only to avoid a few keystrokes. Your code should definitely not compile according to the standard, and the example you quoted from cppreference.com may soon become explicitly disallowed as well (I don't think it was valid in the first place). GCC and Clang yield different results for both these examples. Even if they compile today, they may fail tomorrow in the next compiler version.
Long version
Regarding the example from cppreference.com, let's first note that Clang 3.6.0 compiles the code, but GCC 5.1.0 rejects both s.set<T>() and s.template set<T>() with the error invalid use of 'class std::set<T>'. I don't think either of the two compilers does the right thing here according to the standard, but, intuitively, GCC's error message makes a lot of sense: what would be the meaning of s.set<T>() with set<T> being a class template specialization?
With your code, it's the other way around: Clang rejects it (the error message quoted in the question seems to be actually from Clang) and GCC compiles it.
The examples rely on paragraph [3.4.5p1] in the standard (emphasis mine in all quotes):
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.
The class template part is the reason for your code being rejected by Clang (your func is a function template). Function templates were removed from there as the resolution of defect 141, included in C++11. It's worth mentioning a comment in the defect report:
There do not seem to be any circumstances in which use of a non-member
template function would be well-formed as the id-expression of a class
member access expression.
I think this says something about the intent of this lookup rule: it's supposed to find constructs that are well formed; it's not intended to just make the parser happy about those <> with some temporary match that will later be replaced by something else with entirely different semantics.
Even with the special lookup rule above, I'm not sure the standard allows you to omit the template in such cases. Paragraph [14.2p4] says:
When the name of a member template specialization appears after . or
-> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object expression of the postfix-expression is
type-dependent or the nested-name-specifier in the qualified-id refers
to a dependent type, but the name is not a member of the current
instantiation (14.6.2.1), the member template name must be prefixed by
the keyword template. Otherwise the name is assumed to name a
non-template.
Both member templates set and func in the two examples satisfy the conditions in there, respectively. As you can see, there's no mention of an exception to this rule.
Or, to put it another way, if you want set to be resolved as the name for the member template, it has to have template in front of it. If it doesn't, it can be resolved as the namespace-scope set, but then the set name itself is no longer a name dependent on template parameters (set<T> is still dependent, but set itself is not). And then we get to [14.6p10], which says:
If a name does not depend on a template-parameter (as defined in
14.6.2), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template
definition; the name is bound to the declaration (or declarations)
found at that point and this binding is not affected by declarations
that are visible at the point of instantiation.
Once bound, it's carved in stone and the later switch to the member template is not valid, which makes the cppreference.com example incorrect.
Moreover, there's an open issue regarding the applicability of the lookup rule from [3.4.5p1] to such examples - issue 1835. Quoting a note in there:
One possibility might be to limit the lookup to the class of the
object expression when the object expression is dependent.
The issue is in drafting status, which means informal consensus has been reached in the working group. Exactly what that consensus was remains to be seen, but I'd say there's a good chance that something will change. Relying on such code doesn't seem like a good idea.
The quoted paragraphs have remained unchanged since C++11 up to the current working draft (N4431).
When the compiler tries to resolve i.template hi<T>(); it finds hi in the global namespace instead of the method hi on i (ideone). Why?
#include <cstdio>
// Define 'hi' and 'bye' in the global namespace; these should *not* be used
template<typename T> struct hi { };
template<typename T> struct bye { };
// Foo needs to be templated for Foo::Inner to be a dependent type (I think)
template<typename T>
struct Foo
{
struct Inner {
// This is a plain-old templated member function of Inner, yes?
template<typename U>
void hi() { std::printf("hi!\n"); }
// This is a plain-old member function of Inner
void bye() { std::printf("bye!\n"); }
};
void sayStuff()
{
Inner i;
i.template hi<T>(); // Fails to compile -- finds global hi instead of member
i.bye(); // Compiles fine, finds member
}
};
int main() {
Foo<int> f;
f.sayStuff();
return 0;
}
I'm using g++ 4.9.1/4.9.2 (-std=c++11). The exact error message:
prog.cpp: In member function 'void Foo<T>::sayStuff()':
prog.cpp:19:5: error: invalid use of 'struct hi<T>'
i.template hi<T>();
^
This code works fine with Clang and VS2013, but generates an error in g++ and EDG. But which compilers are right?
Is there any way to resolve this besides changing the name of the member? In my real code, the conflict arises when a type from the std namespace (that's been imported via using namespace std, say) has the same name as one of my member functions. Obviously I'd like my implementation code to be robust and not cause random name clashes in user code.
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.
The following code compiles on GCC (doesn't even require a recent version), but it fails on clang 3.4:
template <int N>
struct T_unsigned {
typedef typename T_unsigned<N>::Type Type;
};
template <> struct T_unsigned<8> {
typedef unsigned char Type;
};
Using the above definition of T_unsigned, GCC allows you to use "T_unsigned<8>::Type" instead of "unsigned char". When I try to compile this using clang 3.4, I get:
test.cpp:3:41: error: no type named 'Type' in 'T_unsigned<N>'
typedef typename T_unsigned<N>::Type Type;
~~~~~~~~~~~~~~~~~~~~~~~~^~~~
1 error generated.
Is clang failing to compile correct C++11 code, or is this code doing something non-standard that GCC happens to support?
In your general case T_unsigned<N>, we have:
A name is a member of the current instantiation if it is
[...]
A qualified-id in which the nested-name-specifier refers to the current instantiation.
[ Example:
template <class T> class A {
static const int i = 5;
int n1[i]; // i refers to a member of the current instantiation
int n2[A::i]; // A::i refers to a member of the current instantiation
int n3[A<T>::i]; // A<T>::i refers to a member of the current instantiation
int f();
};
Within T_unsigned<N>, T_unsigned<N> is just another name for itself. So basically you have something like:
class Foo {
typedef Foo::Type Type;
};
and the "correct" error message should be approximately (http://ideone.com/FvJHBF):
prog.cpp:2:17: error: ‘Type’ in ‘class Foo’ does not name a type
typedef Foo::Type Type;
^
However, you write that you have problems with using your specialization T_unsigned<8>, which is seemingly not found by clang.
Your testcase is not too exhaustive, so my answer depends on an if-statement:
If at the point of instantiation, your specialization for N=8 is visible, than clang is doubly wrong. If not, gcc and clang should both fail, but with aforementioned error message (though the error message itself is in no way defined by the standard, so this is a tool's should, not a standard's).
The name that you use as the typedef is not dependent (see the clauses that define dependent names) and the namelookup in definition context at that place will not find a declaration. That in itself is an error already.
But since there is no declaration for the name yet, the name is also not a member of a class that is the current instantiation or a base class thereof. Therefore the name is not a member of the current instantiation and therefore we have another reason to reject it by a rule that says that if the qualifier is the current instantiation, the name either must refer to a member of that instantiation, or to a member of an unknown specialization (which would be the case if the class had dependent base classes).
Note the notion of "current instantiation": the meaning of the qualifier is fixed to refer to the result of instantiating the surrounding template, we don't wait for resolving the template arguments. Hence the term is not called "current specialization", since we know that it refers to an instantiated specialization, as opposed to a later declared explicit specialization.
The thing is different for C++03 I think. The name will be dependent and the template definition is harder to deem illformed with the rules available. The illformed, no diagnostic required, behavior will however happen when you try to instantiate the template before providing the explicit specialization. I think such code refering to itself makes no sense because you never are able to actually instantiate the template validly (and there is a rule that allows rejecting a template straight away in such cases).
There are a lot of questions at this site with the problems while compiling c++ template code. One of the most common solutions to such problems is to add typename (and, less frequently, template) keyword in the right places of the program code:
template<typename T>
class Base
{
public:
typedef char SomeType;
template<typename U>
void SomeMethod(SomeType& v)
{
// ...
}
};
template<typename T>
class Derived : public Base<T>
{
public:
void Method()
{
typename Base<T>::SomeType x;
// ^^^^^^^^
this->template SomeMethod<int>(x);
// ^^^^^^^^
}
};
Whether there is a code that compiles both with and without keyword typename and gives different results (e.g. output strings)? Similar question for template keyword.
If not, whether these keywords are really necessary in such meanings?
A small overview of the current situation
#Paul Evans wrote a good answer but it is more suitable for the question "Where and why do I have to put the “template” and “typename” keywords?", not for my question.
#Simple gave an example of the required code for typename keyword and its possible variation. #Jarod42 gave another variation without any templates, which is probably a gcc bug because it does not compile with clang.
#n.m. gave an example of the required code for template keyword, #dyp improved it. #n.m. also wrote the another code for both keywords using SFINAE.
#James Kanze in his answer argues that it is impossible to write the required code and any attempts to do it will result in undefined behavior. So the above examples of code are illegal.
It is interesting to find out who is right and what the C++ standard says about this.
The rule is: typename has to be used whenever a name that depends on a template parameter is a type. There are clear cases where it's needed, consider
template <typename T>
class Foo {
typename T::type * p;
//...
};
Here, the second typename is used to indicate that type is a type defined within class T. Thus, p is a pointer to the type T::type.
Without typename, type would be considered a member of class T. So the expression:
T::type * p
would be a multiplication of the type member of class T with p.
Similarly, the rule is: .template, ->template or ::template must be used when accessing a template member that uses a template parameter. Consider:
p->template SomeMethod<int>(x);
without the use of template, the compiler does not know that the < token is not less-than but the start of a template argument list.
By definition, it is impossible to write code which differs in
meaning with or without the keyword; any attempt to do so will
result in undefined behavior. The only purpose of these
keywords (at least in this context) is to allow the compiler to
fully parse the template before instantiation: in order to
correctly parse C++, the compiler must know whether a symbol
designates a type, a template or something else.
Once you instantiate the template, the compiler no longer really
needs the keywords; they have no impact on name lookup, or
anything else. The only particularity is that if the name found
puts a lie to your declaration (you said type, and in the
instantiation, it isn't a type), undefined behavior occurs. If,
for example, the compiler has stored the template in the form of
a parse tree, this parse tree will be incorrect, and who knows
what that might imply.
I would expect that most good compilers would note the category
in the first parse, and if name lookup returns something else,
emit an error, but for historical reasons, I suspect that there
are still compilers which more or less ignore the template or
typename in this context, treating it as a comment; store the
template as a sequence of tokens, and only parse once the
template is instantiated, using the categories it actually finds
in the instantiation.
EDIT:
I've been rereading parts of the standard, and I'm no longer
sure that there is undefined behavior. C++11, at least, says:
A name used in a template declaration or definition and that is
dependent on a template-parameter is assumed not to name a type
unless the applicable name lookup finds a type name or the name
is qualified." by the keyword typename.
When a qualified-id is intended to refer to a type that is not
a member of the current instantiation and its
nested-name-specifier refers to a dependent type, it shall be
prefixed by the keyword typename, forming
a typename-specifier. If the qualified-id in
a typename-specifier does not denote a type, the program is
ill-formed.
Ill-formed usually (but not always) requires a diagnostic. (As
mentioned above, I would expect a compiler to issue a diagnostic
in any case.)