I am writing a cross-platform application in two compilers (Clang on Xcode v5.0.2, and Visual Studio 2012 Update 4) and I have run into a scenario in which the two compilers disagree about the required syntax for the use of the template
keyword in a nested declaration.
Here is the code (boiled down to an easily reproducible test case):
template<typename T>
struct Base
{
template<typename U>
struct InnerBase
{};
};
template<typename T, typename U>
struct Derived : public Base<T>
{
// the "template" keyword is REQUIRED in Clang/OSX
struct InnerDerived : public Base<T>::template InnerBase<U>
{};
// the "template" keyword is FORBIDDEN in Visual Studio 2012
struct InnerDerived : public Base<T>::InnerBase<U>
{};
};
int main()
{
Derived<int, int>::InnerDerived foo;
}
As noted, the two compilers disagree about the use of the "template" keyword.
For Clang, when the template
keyword is not included, the error is:
Use 'template' keyword to treat 'InnerBase' as a dependent template name
For Visual Studio, when the template
keyword is included, the error is:
'Base::InnerBase' : use of class template requires template argument list
I have looked at various other StackOverflow questions regarding the rules for use of the template
keyword (for example, Where and why do I have to put the "template" and "typename" keywords?). However, looking at this, and other similar questions, does not give me confidence in claiming that one compiler is correctly implementing C++11 and that the other is not.
(Note that Clang's error makes sense to me, while the VS error doesn't make much sense to me because it seems that I am including the template argument list.)
Which compiler is correct in this case? Should the template
keyword be included, or not, in the sample code above (for C++11 compliance)?
(Possibly I have not set the compiler settings correctly to use C++11 in one or the other case - in which case, my question still stands: which version of the code above is correct C++11 code?)
5. Which keyword is used for the template? Explanation: C++ uses template reserved keyword for defining templates.
(GNU C is a language, GCC is a compiler for that language. Clang defines __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ according to the version of gcc that it claims full compatibility with.
C++ adds two new keywords to support templates: 'template' and 'typename'. The second keyword can always be replaced by the keyword 'class'.
" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.
It seems the relevant clause is 14.2 (temp.names) paragraph 4:
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 keywordtemplate
.
I think that says that template
is required. Following up with DyP's comment, it seems certainly wrong to reject the keyword even if it isn't required (paragraph 5 of the same clause):
A name prefixed by the keyword
template
shall be a template-id or the name shall refer to a class template. [Note: The keywordtemplate
may not be applied to non-template members of class templates. —end note] [Note: As is the case with thetypename
prefix, thetemplate
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].
Clang is correct, Base<T>
is dependent on a template parameter. This is yet another symptom of Visual C++ not implementing two-phase name lookup for templates.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With