I'm aware of the guidance to not use using
in C++ header files, the reasons for which have been widely discussed, e.g. here.
I was looking for a more C++ alternative to typedef
when I came to this article describing "alias declaration."
Now, just because concepts are getting jumbled in my head, I'm unclear whether the guidance against using using
in headers is specifically for this way of using it:
// my_header.h
#ifndef MY_HEADER_H
#define MY_HEADER_H
using namespace std;
#endif
...or does it also apply to alias declarations?
I want to use typedef/alias declarations/something functionally equivalent because of this situation:
// my_header.h
#ifndef MY_HEADER_H
#define MY_HEADER_H
#include <tuple>
// This function's signature is getting cumbersome
int func(const std::tuple<a::really::long_namespaced::thing, a::really::long_namespaced::thing, a::really::long_namespaced::thing>& tup = {1, 2, 3});
#endif
Basically, a function signature is unwieldy because how long the text of its arguments is.
What's a generally accepted way of making this more readable if using
for an alias declaration is discouraged in header files?
using
keyword has a few meanings:
using namespace X;
brings all the names from namespace X
into current namespace. This is very bad in header files, since every user of this header will risk name conflicts with any name that exists in X
. Especially namespace std
has a lot of very common names, so you'd force users of your header to avoid a lot of good names. It also makes code brittle, since simply adding another header in header with using namespace
can break code in opposite corner of repository that happens to use one of the names already.using X::Y;
bring just one name Y
from namespace X
into current namespace. For example, using std::string;
allows to use string
as a name, but vector
still requires std::
. This still can cause confusion as to what this type really is, but at least it doesn't bring all the names in.using A = X::Y;
introduces a new name into your namespace. Instead of std::tuple<a::really::long_namespaced::thing, a::really::long_namespaced::thing, a::really::long_namespaced::thing>
you can provide a new name that describes the meaning of this type better. In my opinion, this would be preferable in your case (std::tuple
doesn't convey a lot of meaning, a well chosen name would make it easier to read, type and comprehend).Additionally, you can alias namespaces as well. namespace shortName = a::really::long_namespaced;
can solve an issue with long namespace used often in your code. A common example from standard library is namespace fs = std::filesystem
to allow writing e.g. fs::path
instead of std::filesystem::path
. This is better than 2. IMHO, because you keep some reference to where the name is from.