0

I am reading a C++ code and I came across the use of the keyword typename in the middle of the class definition.

Here is the class definition and the keyword is used in the protected section.

template<typename CVertex, typename CEdge, typename CFace, typename CHalfEdge>
class CBoundary
{
    typedef CLoop<CVertex,CEdge, CFace, CHalfEdge> TLoop;

public:

    CBoundary( CBaseMesh<CVertex,CEdge,CFace,CHalfEdge> * pMesh );

    ~CBoundary();

    std::vector<TLoop*> & loops() 
    { 
        return m_loops; 
    } 

protected:

    CBaseMesh<CVertex,CEdge,CFace,CHalfEdge> * m_pMesh;

     typename std::vector<TLoop*> m_loops;

    void _bubble_sort( std::vector<CLoop<CVertex, CEdge, CFace, CHalfEdge>*> & loops);
};

Is this the same as the typedef keyword? There seem to be a couple of related questions like so but I did not really understand the explanation there.

In fact since typename is one of the SO tags I will list the explanation which I did not understand

typename is a keyword in the C++ programming language with two meanings. First, it can be used to declare type arguments inside a template declaration, and is synonymous with "class." Second, it can be used to indicate that a dependent name refers to a type. A common cause of errors in C++ code is the omission of an essential typename.

It looks like I am dealing with the second use here. But I don't understand what "dependent name" means here.

I am just a beginner in template metaprogramming with C++ so a simple explanation of the use in the class above would be very helpful.

Community
  • 1
  • 1
smilingbuddha
  • 14,334
  • 33
  • 112
  • 189

4 Answers4

2

In simple words, "dependent name" in a template code is some type which is constructed within the definition of the template.

In your example, the types CVertex, CEdge, CFace, CHalfEdge are template parameters. All other names which are declared with usage of the parameters are dependent.

They can be type names but can be something else, e.g. name of the functions or variables. Compiler has to understand, whether a given dependent name is a type or a variable. It is actually compiler-dependent. To help the compiler, you add "typename" to indicate that this identifier is a type.

Imagine, that your code does not have #include <vector> but instead uses forward declaration: namespace std { template<class T, class Alloc=allocator<T> > class vector; }

Then compiler has no idea which names within class vector are types and which are member names. It only knows that vector is a type.

For example, in the code typename std::vector<TLoop*> m_loops; most likely the word typename can be omitted for most compilers because they know that vector is a type.

However, the code std::vector<TLoop*>::const_iterator will sure require typename: for (typename std::vector<TLoop*>::const_iterator it = loops().begin(); ...

Hope it helps.

Michael Simbirsky
  • 3,045
  • 1
  • 12
  • 24
2
template <typename T>
struct A
{
    typedef T type;
    static T static_var;
};

template <typename T>
struct B
{
    typename T::type var;
};

Imagine I instantiate B<A<int>>. The compiler will, effectively, try to substitute A<int> wherever I have written T in the second definition. The trouble is, when it gets to T::type, it doesn't know whether I'm referring to a nested type, or a static variable -- both declarations look the same.

Sometimes it can disambiguate by the context in which it is used, but often it can't. Where it can't, you have to tell it that T::thing is the name of a type, by using the typename keyword.

Tristan Brindle
  • 16,281
  • 4
  • 39
  • 82
0

In the code you showed, typename is a synonym for class. It means the parameter is a type.

It has other uses in other contexts however. Whenever T1 depends on a template parameter and you want to reference T1::T2, you have to say typename T1::T2 instead, to let the compiler know T2 is a type -- otherwise it's treated like a function or a variable.

user541686
  • 205,094
  • 128
  • 528
  • 886
0

The way that I think of typename when used with templates is that it is specifying that the identifier coming after the typename keyword is a type. The result is that when a template is used and a type is specified in the template arguments, C++ knows that it is a type and will expand the template correctly. It is a way of saying unambiguously that some identifier in the template argument list is a type such as a class name or a built in type or whatever.

There appear to be certain circumstances when the context may not be clear that a type specified in the template argument is a type so typename is used to make it unambiguous.

For instance see this wikipedia article on typename

And this article may be of assistance as well, Template and typename keywords in C++.

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106