typename

From Wikipedia, the free encyclopedia
Jump to: navigation, search

"typename" is a keyword in the C++ programming language with two distinct uses related to templates. It is a synonym for "class" in template parameters, and it is used for specifying that a dependent name in a template definition or declaration is a type.[1][2]

A synonym for "class" in template parameters[edit]

In C++'s generic programming feature known as "templates", typename can be used for introducing a template parameter:[1][2]

// Define a generic function that returns the greater of its two arguments
template <typename T>
const T& max(const T& x, const T& y)
{
  if (y < x)
    return x;
  return y;
}

An alternative and semantically equivalent keyword in this scenario is "class":

// Define a generic function that returns the greater of its two arguments
template <class T>
const T& max(const T& x, const T& y)
{
  if (y < x)
    return x;
  return y;
}

A method for indicating that a dependent name is a type[edit]

Consider this invalid code:

template <typename T>
void foo(const T& t)
{
   // declares a pointer to an object of type T::bar
   T::bar * p;
}
 
struct StructWithBarAsType {
   typedef int bar;
};
 
int main() {
   StructWithBarAsType x;
   foo(x);
}

This code looks like it should compile, but it is incorrect because the compiler does not know if T::bar is a type or a value. The reason it doesn't know is that T::bar is a "template-parameter dependent name", or "dependent name" for short, which then could represent anything named "bar" inside a type passed to foo(), which could include typedefs, enums, variables, etc.

To resolve this ambiguity, the C++ Language Standard declares:

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

In short, if the compiler can't tell if a dependent name is a value or a type, then it will assume that it is a value.

In our example, where T::bar is the dependent name, that means that rather than declaring a pointer to T::bar named "p", the line

  T::bar * p;

will instead multiply the "value" T::bar by p (which is nowhere to be found) and throw away the result. The fact that in StructWithBarAsType the dependent bar is in fact a type does not help since foo() could be compiled long before StructWithBarAsType is seen. Furthermore, if there is also a class like:

struct StructWithBarAsValue {
    int bar;
};

then the compiler would be obliged to interpret the T::bar in foo() as an access to data member StructWithBarAsValue::bar when instantiated. But since bar is not a static data member it will flag an error.

The solution to this problem is to explicitly tell the compiler that T::bar is in fact a type. For this, the typename keyword is used:[1][2]

template <typename T>
void foo(const T& t)
{
   // declares a pointer to an object of type T::bar
   typename T::bar * p;
}

Now the compiler knows for sure that T::bar is a type, and will correctly make p a pointer to an object of that type.

References[edit]

  1. ^ a b c "The typename keyword (C++ only)". IBM. Retrieved 23 August 2013. 
  2. ^ a b c "MSDN - typename". MSDN. Retrieved 23 August 2013. 

See also[edit]