Jste zde

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

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í

Komentáře

Ahoj,

není v typedef std::map<std::string, T>> type; navíc znak `>' ?

Jo jo :). Opravil jsem to. Díky.

Přidat komentář