Zajímavosti z C++: Rozdíl mezi 'class' a 'typename' při definici šablony

Od Petr Zemek, 2012-04-03

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.

Obsah tohoto pole je soukromý a nebude veřejně zobrazen.

Filtrované HTML (využíváno)

  • Povolené HTML značky: <a href hreflang> <em> <strong> <cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <table>
  • Zvýraznění syntaxe kódu lze povolit přes následující značky: <code>, <blockcode>, <bash>, <c>, <cpp>, <haskell>, <html>, <java>, <javascript>, <latex>, <perl>, <php>, <python>, <ruby>, <rust>, <sql>, <text>, <vim>, <xml>, <yaml>.
  • Řádky a odstavce se zalomí automaticky.
  • Webové a e-mailové adresy jsou automaticky převedeny na odkazy.
CAPTCHA
6 + 9 =
Vyřešte tento jednoduchý matematický příklad a vložte výsledek. Např. pro 1+3 vložte 4.
Nějak se mi tady rozmohl spam, takže poprosím o ověření.