Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it required to specify the template argument of a base class if the base class is a parameter type of a member function?

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;
}
like image 337
xmllmx Avatar asked Jun 19 '14 13:06

xmllmx


People also ask

What is template What is the need of template declare a template class?

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.

Can function be a template argument?

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.

CAN default arguments be used with the template?

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 { };

Which is the correct example of template parameters?

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.


1 Answers

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

  1. it's a nice corner-case, and

  2. clang is actually right not to examine the scope of A<T>

like image 162
Angew is no longer proud of SO Avatar answered Oct 06 '22 23:10

Angew is no longer proud of SO