O možnosti vytváření aliasů na typy pomocí konstrukce typedef
ví zřejmě každý programátor v C a C++. Co je však méně známé, tak je, že v C++ si můžete vytvářet aliasy na jmenné prostory. Tento příspěvek vám ukáže, jak na to a vysvětlí, k čemu se to může hodit.
Úvod aneb kde typedef nestačí
Pokud máte složitý typ, např.
std::map<std::string, std::set<std::string> >
tak se vám pro zpřehlednění kódu může vyplatit si udělat typový alias. K tomu slouží konstrukce typedef
:
typedef std::set<std::string> StringSet; typedef std::map<std::string, StringSet> NameToNicknamesMap;
Co když ale používáte složitě zanořené prostory jmen? Např. chcete používat různé třídy z fslibrary::filesystem::io
:
fslibrary::filesystem::io::input_stream istream("file1.txt"); fslibrary::filesystem::io::output_stream ostream("file2.txt");
Většina lidí vám doporučí použít using
direktivu či deklaraci. Pokud jste si ale vědomi problémů, do kterých se použitím using
můžete dostat (zaneřádění jmenných prostorů a další), budete se pídit po jiném řešení. Co takto použít typedef
? Zní to slibně, ale pokud to zkusíte, tak narazíte, protože ten funguje pouze pro typy, nikoliv pro prostory jmen.
Naše záchrana: aliasy na prostory jmen
C++ nám již od ISO C++98 umožňuje používat tzv. aliasy na prostory jmen (angl. namespace aliases). Jejich syntaxe je následující:
namespace alias_name = some_long_namespace;
Výše uvedený kód bychom tedy mohli přepsat takto:
namespace fsio = fslibrary::filesystem::io; fsio::input_stream istream("file1.txt"); fsio::output_stream ostream("file2.txt");
Pokud používáte mnoho tříd z onoho jmenného prostoru, bude výsledné řešení mnohem čitelnější.
K čemu je to ještě dobré?
Jak jsme již viděli, hodí se to v případě, kdy chcete zjednodušit a zpřehlednit kód, aniž byste se zapletli do možných problémů vyplývajících s použití using
direktivy/deklarace. Je ještě jiné možné použití? Představte si, že máte dvě různé implementace souboru tříd: jedna implementace podporuje vícevláknové zpracování, ta druhá ne. Pak můžete v kódu, který tyto třídy využívá používat jediný prostor jmen (alias) a někde mít umístěný následující kód, kterým vám vybere vhodný alias v závislosti na podpoře vícevláknového zpracování:
#if THREADS_ARE_SUPPORTED_ON_THE_PLATFORM namespace mylib = myproject::mylibrary::impl_with_threads; #else namespace mylib = myproject::mylibrary::impl_without_threads; #endif
Dále vám v kódu stačí využívat mylib::
a nemusíte se starat o to, zda jsou na dané platformě podporována vlákna či nikoliv.