The following code is accepted by VC++ 2013, but rejected by clang 3.4.
Which compiler is right as per the C++ standard?
template<class T>
struct A
{
T n;
};
template<class T>
struct B : A<T>
{
// VC++ 2013 : OK
// clang : error : use of class template 'A' requires template arguments
B& f1(const A& obj)
{
return *this;
}
// VC++ : OK
// clang : OK
B& f2(const A<T>& obj)
{
return *this;
}
};
int main()
{
B<int> b;
}
Templates in c++ is defined as a blueprint or formula for creating a generic class or a function. To simply put, you can create a single function or single class to work with different data types using templates.
A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };
For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.
My first instinct is to say VC++ is right in this one. Lookup of the name A
in B
should find the injected-class-name A
inside A<T>
, which can also be used as a type-name to refer to A<T>
.
C++11 [temp.local]:
1 Like normal (non-template) classes, class templates have an injected-class-name (Clause 9). The injected-class-name can be used as a template-name or a type-name. When it is used with a template-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-type-specifier of a friend class template declaration, it refers to the class template itself. Otherwise, it is equivalent to the template-name followed by the template-parameters of the class template enclosed in
<>
.2 ...
3 The injected-class-name of a class template or class template specialization can be used either as a template-name or a type-name wherever it is in scope. [ Example:
template <class T> struct Base { Base* p; }; template <class T> struct Derived: public Base<T> { typename Derived::Base* p; // meaning Derived::Base<T> };
However, at the same time, [temp.dep]§3 states:
3 In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.
Based on this, I'd more inclined to say that clang is actually right, since the injected-class-name A
is inside the scope of A<T>
, which depends on B
's template parameter T
and is thus not searched during unqualified name lookup. Secondary evidence to support this would be the fact that the example from [temp.local] uses Derived::Base
instead of just Base
.
So in total, I'd say that
it's a nice corner-case, and
clang is actually right not to examine the scope of A<T>
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