Proč v C++ preferovat using před typedef

Od Petr Zemek, 2015-08-15

Od C++11 přibyly tzv. typové aliasy (using TypeAlias = OriginalType;). Jedná se o alternativu pro klasický typedef. V příspěvku uvedu několik důvodů, proč od C++11 na typedef zapomenout a využívat pouze typové aliasy.

Jak typové aliasy fungují

V C či C++98 se dá alias na jiný typ zavést pomocí typedef:

typedef OriginalType TypeAlias;

Od C++11 lze vytvořit typový alias taktéž přes klíčové slovo using:

using TypeAlias = OriginalType;

Obě formy jsou ekvivalentní a není mezi nimi rozdíl [C++14, §7.1.3.2].

Proč od C++11 preferovat typové aliasy

Když mezi nimi není rozdíl, tak proč preferovat using? Z následujících třech důvodů:

1) using umí vše, co typedef

Jen pro úplnost.

2) using je čitelnější a konzistentní

U using se název aliasu nachází vždy na stejném místě: za klíčovým slovem using. U typedef tomu tak není. Vezměme si např. následující typové aliasy:

typedef unsigned int Size;                        // Název aliasu je vpravo.
typedef std::size_t (*HashFunc)(const MyClass &); // Název aliasu je uprostřed.

U using je název aliasu vždy vlevo:

using Size = unsigned int;
using HashFunc = std::size_t (*)(const MyClass &);

Usnadňuje to orientaci.

3) using zvládá aliasy na šablony lépe, než typedef

S pomocí using si lze jednoduše vytvořit alias na neúplně specifikovanou šablonu:

// Zavedení typového aliasu.
template <typename T>
using Dictionary = std::map<std::string, T>;
 
// Použití.
Dictionary<int> d;

Toto s pomocí typedef není možné napsat. Resp. je, ale složitěji a oklikou:

// Zavedení "typového aliasu".
template <typename T>
struct Dictionary {
    typedef std::map<std::string, T> type;
};
 
// Použití.
Dictionary<int>::type d; // Zde je potřeba uvést '::type'.

Jak vidíme, definice typového aliasu i jeho použití je v případě typedef složitější a méně čitelné. Navíc, pokud bychom onen alias použili uvnitř jiné šablony, tak u řešení získaného přes typedef bychom museli použít typename:

template <typename T>
class MyClass {
    // ...
 
    typename Dictionary<T>::type d; // Zde je potřeba 'typename', protože typ '::type' závisí na T.
};

Toto u řešení s pomocí using odpadá:

template <typename T>
class MyClass {
    // ...
 
    Dictionary<T> d;
};

Od C++11 tedy doporučuji na typedef zapomenout a používat pouze using. Používání obou forem zároveň přináší akorát nekonzistenci.

Zdroje a další čtení

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
8 + 4 =
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í.