Short version
Do not rely on this. Use the template keyword as you expected, do not try to use such an obscure hack to avoid a few keystrokes. Your code should definitely not compile in accordance with the standard, and the example you provided from cppreference.com may soon also be explicitly forbidden (I donβt know) I think it was really in the first place). GCC and Clang give different results for both of these examples. Even if they compile today, they may fail tomorrow in the next version of the compiler.
Long version
As for the example from cppreference.com , 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 invalid use of 'class std::set<T>' 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, the GCC error message makes a lot of sense: what will the value of s.set<T>() with set<T> being the class template specialization?
This is the opposite with your code: Clang rejects it (the error message mentioned in the question seems to be actually related to Clang), and GCC compiles it.
Examples are based on paragraph [3.4.5p1] in the standard (highlighted in all citations):
In an access expression to a member of a class (5.2.5), if. or β a token followed by an identifier followed by an identifier <, the identifier must be checked to determine if the list of arguments to the template (14.2) is the beginning or less than the operator. The identifier is first looked up in the object expression class. If the identifier is not found, then it is looked in the context of the entire postfix expression and we will call the template class .
Part of the class template causes your code to abandon Clang (your func is a function template). Function templates were removed from there as the resolution of defect 141 included in C ++ 11. It is worth mentioning the comment in the defect report:
There seems to be no circumstance under which the use of a non-member template function will be correctly formed as an id-expression of the member-expression class.
I think this suggests the intent of this search rule: it must find well-formed constructions; it is not intended to simply make the parser happy about those <> with some temporary coincidence, which will later be replaced by something else with completely different semantics.
Even with the help of the special search rule above, I'm not sure if the standard allows you to omit template in such cases. Paragraph [14.2p4] states:
When then the member template specification appears. or β in a postfix expression or after a nested qualifier name in qualified-id, and the postfix-expression object expression is a type-dependent or nested name qualifier in the identifier with qualification-id to a dependent type, but the name is not a member of the current one (14.6.2.1 ), the name of the member template must be prefixed with the keyword template . Otherwise, it is assumed that the name is without a pattern.
Both set and func member templates in two examples satisfy the conditions there, respectively. As you can see, there is no mention of an exception to this rule.
Or, in other words, if you want set to resolve as the name of a member template, it must be preceded by template . If this is not the case, it can be resolved as an area of ββthe set namespace, but then the set name itself is no longer a name depending on the template parameters ( set<T> is still dependent, but set itself is not). And then we get to [14.6p10], which says:
If the name does not depend on the template parameter (as defined in 14.6.2), the declaration (or set of declarations) for this name should be in scope at the point where the name is displayed in the template definition; the name is associated with the declaration (or declarations) found at that moment, and this obligation does not depend on the announcements that are visible at the time the instance was created.
After binding, it is cut out on the stone, and a later transition to the member template is not allowed, which makes the cppreference.com example incorrect.
In addition, there is an open problem regarding the applicability of the search rule from [3.4.5p1] to such examples - issue 1835 . Quoting notes:
One possibility might be to limit the search for the class expression of an object when the expression of the object is dependent.
The issue is developing status, which means that informal consensus has been reached in the working group. The fact that this consensus remains remains to be seen, but I would say that there is a good chance that something will change. Relying on such code does not seem like a good idea.
The indicated paragraphs remained unchanged from C ++ 11 until the current working draft (N4431).