Asi jste se již setkali s tím, že někdo při definici šablony používal klíčové slovo typename
a někdo jiný zase class
. O tom, zda je mezi nimi rozdíl a kdy použít které klíčové slovo je následující příspěvek.
O co jde?
Když definujete šablonu, tak můžete pro označení typového parametru použít dvě klíčová slova: class
a typename
. Následující příklad ukazuje obě použití.
template <typename T> void func(const T &p) { // ... }
template <class T> void func(const T &p) { // ... }
Je mezi nimi v tomto použití rozdíl?
Není, viz norma C++98, sekce 14.1.3: There is no semantic difference between class and typename in a template-parameter.
Které z těchto dvou klíčových slov mám tedy používat?
Je to jen na vás. Někteří (old-schooleři) používají pouze class
. Někteří pouze typename
(třeba z důvodů, že je to modernější). Někteří (sem patřím i já) se drží jakési rozšířené konvence, že pokud typem musí být vždy třída, tak použijí class
, jinak použijí typename
(např. když typ může být i primitivní typ jako int
). Jiní se zase na tuto konvenci dívají skrz prsty, že to zbytečně zesložiťuje :). Viz následující odkazy: 1, 2, 3.
Jsou situace, kdy je mezi nimi rozdíl?
Ano. Vím o čtyřech případech, kdy jedno nemůžete zaměnit za druhé.
První (očividný) případ je ten, kdy definujete třídu:
class A { // ... };
Druhý případ je, pokud v šabloně definujete typ, který závisí na typu vnořeném v šablonovém parametru:
template <typename T> class A { void f() { typename T::X *p; // ... } };
Pokud byste nepoužili klíčové slovo typename
před T::X
, narazili byste na problém (detaily).
Třetí případ nastane, když definujete šablonu, kde jeden z typových parametrů je šablona (tzv. template template parametr).
template <template <typename, typename> class ContainerType, typename ValueType> class A { // ... };
Čtvrtým případem je, když chcete provést explicitní instanciaci šablony pro šablonovou třídu:
template class A<int>;
Proč existují pro to samé dvě klíčová slova?
Jak už asi tušíte, tak důvod je historický. Bjarne Stroustrup při tvorbě jazyka použil class
, aby nemusel zavádět nové klíčové slovo. Bohužel ale nastaly případy, kdy bylo zavedení nového klíčového slova vhodné řešení (viz sekce Jsou situace, kdy je mezi nimi rozdíl?), a tak se standardizační komise rozhodla zavést nové klíčové slovo: typename
. To pak bylo možno použít i v definici šablony. Pro více detailů si přečtěte tento příspěvek.