What lies behind the words "typename" and "class"? Differences you must know
\n\nIf you have ever written C++ templates, you have certainly encountered two seemingly interchangeable keywords: typename and class. It looks like a minor detail, but on Stack Overflow, this question has gathered thousands of views. Why? Because beneath the apparent simplicity lies a pitfall that can break your code compilation.
In this article, we will settle the matter once and for all: what is the difference between typename and class in C++ templates, when they can be used as synonyms, and when this will lead to an error. No fluff — only code, examples, and clear rules.
\n\nShort answer: is there even a difference?
\n\nThe most popular answer on Stack Overflow is: for declaring template parameters — there is no difference. You can write:
\n\ntemplate <typename T> void foo(T t);\nor
\ntemplate <class T> void foo(T t);\n\nBoth options are perfectly legal and do the same thing: declare a template parameter T. Historically, class appeared first (back in C++98), and typename was added later to emphasize that the parameter could be not only a class but any type (int, double, pointer, etc.).
However, the devil is in the details. There is one scenario where typename is mandatory, and class will not work. And that is — dependent names.
The main pitfall: dependent types
\n\nImagine this situation: you are writing a template, and inside it, you refer to a type nested within the template parameter. For example, you have a container and you want to get its iterator:
\n\ntemplate <typename Container>\nvoid printFirst(const Container& c) {\n Container::const_iterator it = c.begin(); // ERROR!\n std::cout << *it;\n}\n\nWhy doesn't this compile? Because Container::const_iterator is a dependent name. At the parsing stage, the compiler does not know what Container is. It could be a class, or it could be the name of a static variable? By default, C++ assumes that Container::const_iterator is the name of a variable (or a static data member), not a type. Only the keyword typename tells the compiler: "Hey, this is a type!".
Let's fix it:
\n\ntemplate <typename Container>\nvoid printFirst(const Container& c) {\n typename Container::const_iterator it = c.begin(); // OK!\n std::cout << *it;\n}\n\nImportant: here, class will not work. Writing class Container::const_iterator is a syntax error. typename is the only correct option.
When to use typename instead of class?
\n\nRemember this simple rule: typename is used in two cases:
- \n
- As a template parameter (synonym for
class):template <typename T>\n - To indicate that a dependent name is a type:
typename T::value_type\n
And class is only for the first case. Moreover, many C++ programmers prefer typename for parameters to avoid confusion with class declarations.
Complete example with explanations
\n\nLet's break down real code that demonstrates the difference between typename and class in C++ templates in practice:
\n\n#include <iostream>\n#include <vector>\n#include <list>\n\n// Step 1: template with class (or typename — no difference)\ntemplate <class T>\nclass MyContainer {\npublic:\n // Step 2: use typename for a dependent type\n // T::value_type is a type, not a