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).
Related
Consider the following example:
namespace N {
template<class>
struct C { };
template<int, class T>
void foo(C<T>);
}
template<class T>
void bar(N::C<T> c) {
foo<0>(c);
}
int main() {
N::C<void> c;
bar(c);
}
Both GCC and Clang fail to compile this code under C++17 standard (with -Werror), because (according to my understanding) in C++17 ADL doesn't work when explicit template arguments <...> are present (unless a name is already established as a template name), so foo is a non-dependent name that is not found.
In C++20, the ADL rules have changes, and explicit template arguments don't prevent ADL. Now it seems that foo becomes a dependent name that should be resolvable via ADL. However, GCC and Clang have different opinions about the validity of this code. CLang compiles it without errors, but GCC (10.2, -std=c++2a) complains:
error: 'foo' was not declared in this scope; did you mean 'N::foo'?
In C++17 mode, Clang produces the following warning:
warning: use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension
Demo.
I have three related questions:
Which compiler is right and why?
In C++17, is foo in foo<0>(c) considered as a dependent name?
In C++20, is foo in foo<0>(c) considered as a dependent name?
This is P0846, which is a C++20 feature. It appears that gcc does not implement this yet.
It's not a question of dependent name or not, it's a question of does the compiler know that foo refers to a template or not, and so is foo< doing a comparison or is it starting to do template parameters.
In C++17, the compiler had to already know that foo was a template-name (which you could accomplish by adding using N::foo;) in order to perform ADL, in C++20 that's no longer true - now the rule is that if unqualified lookup finds a template or nothing, we also consider it to be a template.
The dependence of foo didn't change as a result of this paper. In foo<0>(c);, foo is still a dependent name. The rule in [temp.dep] from C++17 was:
In an expression of the form:
postfix-expression ( expression-listopt )
where the postfix-expression is an unqualified-id, the unqualified-id denotes a dependent name if
any of the expressions in the expression-list is a pack expansion,
any of the expressions or braced-init-lists in the expression-list is type-dependent, or
the unqualified-id is a template-id in which any of the template arguments depends on a template parameter.
The second bullet applies here - c is type-dependent. The C++20 wording is the same. The issue here wasn't that foo wasn't dependent in C++17. It's just that the rule was when we foo<, we don't know that foo is a template, so it's considered the less-than-operator, and that then fails.
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.
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.)
Check out the following code (written just for fun)
namespace N
{
template<typename T>
struct K
{
};
}
template<typename T>
struct X
{
typename T::template K<T> *p; //should give error
//N::K<int> has no template member named `K`
};
int main()
{
X<N::K<int> > l;
}
The code gets compiled on g++(4.5.1) and Clang whereas Comeau and Intel C++ give (similar) errors.
The errors that I get on Comeau are :
"ComeauTest.c", line 13: error: class "N::K<int>" has no member "K"
typename T::template K<T> *p;
^
detected during instantiation of class "X<T> [with T=N::K<int>]" at
line 18
"ComeauTest.c", line 13: error: expected an identifier
typename T::template K<T> *p;
^
detected during instantiation of class "X<T> [with T=N::K<int>]" at
line 18
So my question is "Is the code sample ill-formed ?" According to me "Yes". Does that mean this is yet another bug in g++/Clang?
Why GCC and Clang think they are right
K, which is the injected class name, has a dual nature in the scope of K<int>. You can use it without template arguments. Then it refers to K<int> (to its own type).
It can be followed by a template argument list too. IMO it's reasonable to say that you need to prefix it with template because of the parser ambiguity with the < that follows. It then refers to the specified type that's determined by the template arguments.
So it can be treated as a member template and as a nested type, depending on whether it's followed by a template argument list. Of course, K is not really a member template. The dual nature of the injected class name seems to me more of a hack anyway, though.
The Standard has an example that reads like this:
template <class T> struct Base { };
template <class T> struct Derived: Base<int>, Base<char> {
typename Derived::Base b; // error: ambiguous
typename Derived::Base<double> d; // OK
};
One might be inclined to conclude from this that the intent is that you could leave off the template. The Standard says
For a template-name to be explicitly qualified by the template arguments, the name must be known to refer to a template.
I can't see how this wouldn't apply to T::K<T>. If T is a dependent type then you can just lean back because you can't know what K refers to when parsing it, so to make any sense of the code, you just have to be able to prefix it with template. Notice that n3225 has that example too, but it's not a defect there: You can officially leave off template if you lookup into the template's own scope in C++0x (it's called the "current instantiation").
So until now, Clang and GCC are fine.
Why Comeau is right
Just to make it even more complicated, we will have to consider the constructors of K<int>. There is a default constructor and a copy constructor implicitly declared. A name K<int>::K will refer to the constructor(s) of K<int> unless the name lookup used will ignore function (constructor) names. Will typename T::K ignore function names? 3.4.4/3 says about elaborated type specifiers, which typename ... is one of:
If the name is a qualified-id, the name is looked up according its qualifications, as described in 3.4.3, but ignoring any non-type names that have been declared.
However, a typename ... uses different lookup. 14.6/4 says
The usual qualified name lookup (3.4.3) is used to find the qualified-id even in the presence of typename.
The usual qualified lookup of 3.4.3 won't ignore non-type names, as illustrated by the example attached to 14.6/4. So, we will find the constructor(s) as specified by 3.4.3.1/1a (the additional twist that this only happens when non-types are not ignored was added by a later defect report, which all popular C++03 compilers implement though):
If the nested-name-specifier nominates a class C, and the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (clause 9), the name is instead considered to name the constructor of class C. Such a constructor name shall be used only in the declarator-id of a constructor definition that appears outside of the class definition.
So in the end, I think comeau is correct to diagnose this, because you try to put a template argument list onto a non-template and also violate the requirement quoted in the last part (you use the name elsewhere).
Let's change it by accessing the injected name by a derived class, so no constructor name translation occurs, and you really access the type so that you really can append the template arguments:
// just replace struct X with this:
template<typename T>
struct X
{
struct Derived : T { };
typename Derived::template K<T> *p;
};
Everything compiles now with comeau too! Notice I already did problem report to clang about this exact thing. See Incorrect constructor name resolution. BTW, if you declare a default constructor in K, you can see comeau give a better error message if you use T::K<int>
"ComeauTest.c", line 13: error: overloaded function "N::K<T>::K [with T=int]" is
not a template
typename T::template K<T> *p;
I'm trying to find any information about template keyword used as disambiguator, but there is nothing about that. Probably I'm searching wrong keywords, but there is nothing like .template or ->template in standard. Google shows only GCC problems from different forums, but not really explanation what is it used for.
Code like that failed to compile without template keyword on line 11 (on GCC), but I'm not quite sure that this conforms standard.
template<typename B>
struct S1
{
template<typename T> void test() {}
};
template<typename T>
struct S2
{
S2()
{
S1<T>().template test<int>();
}
};
int main()
{
S2<int>();
}
So my question is: why does template keyword used here, what kind of ambiguity is there without that keyword and where can I read about that (I would really appreciate link to standard).
Thanks.
Short answer : Because the standard says so
ISO C++03 14.2/4
When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.
P.S:
Without that extra use of template, the compiler does not know that the less-than token (<) that follows is not really "less than" but the beginning of a template argument list.