I’m a big fan of never using using namespace std
. There are a ton of technical reasons, but I want to talk about the readability part. Generally, if it is avoided, it’s easier for somebody checking your code to see which variables are yours. Sure, cout
and cin
are unmistakable, but what about vector
or hash
or pair
? Again, people will have to scroll up to see where they were declared. And they won’t find them, since they weren’t declared anywhere. If I read code, I keep track of the function and object names. If I encounter a variable I don’t know, I need to find out where it came from. And if you randomly throw the word vector
into the code, it will confuse me a lot more than using std::vector
, which is instantly obvious.
But what about partial imports?
Partial imports are things like using std::cout
. I don’t like them. I give them out as advice for people who just won’t drop the whole using namespace std
, but I personally don’t like them. If you want to use a namespace because the lines would be too long, do it locally, i.e.:
double calculate(double x) { using namespace std; return floor(sin(x)/cos(x)) + ceil(cos(x)/2); } void print(std::string s) { // using directive doesn’t apply here! std::cout << s << std::endl; }
But generally I’m against the using
directive. If you want it because of otherwise long names long names you have a few options:
Using auto
Quick, what does this code do?
std::vector<std::chrono::high_resolution_clock::time_point> vec; std::vector<std::chrono::high_resolution_clock::time_point> vec2; // fill both vectors std::vector<std::chrono::duration<long long int, std::ratio<1, 1000000000>>> durations; for(std::chrono::high_resolution_clock::time_point& tp : vec) { for(std::chrono::high_resolution_clock::time_point& tp2 : vec2) { std::chrono::duration<long long int, std::ratio<1, 1000000000>> dur = tp - tp2; std::cout << "Measured: " << dur.count() << std::endl; durations.push_back(dur); } }
No clue? If we use auto
a bunch of times (and one decltype
), it will become apparent:
std::vector<std::chrono::high_resolution_clock::time_point> vec1; std::vector<std::chrono::high_resolution_clock::time_point> vec2; // fill both vectors std::vector<decltype(vec1[0]-vec2[0])> durations; for(auto& tp1 : vec1) { for(auto& tp2 : vec2) { auto dur = tp1 - tp2; std::cout << "Measured: " << dur.count() << std::endl; durations.push_back(dur); } }
Not only is the code easier to read, but we also avoided using namespace std
! (Even that wouldn’t have helped here, we could just have removed the first, small part. Of course, one could have used using namespace std::chrono
, but that introduces yet anotherusing
directive.)
Using typedef
Of course, auto
comes with a lot of trouble if something is deduced incorrectly. So sometimes you need to actually explicitly give a type. One of my favorite ways to do that is using a typedef
struct.
struct timer { typedef std::chrono::high_resolution_clock clock; typedef std::chrono::duration<long long int, std::ratio<1, 1000000000>> duration; // ... }
Now you can use timer::clock
or timer::duration
instead of the long name. Generally, in my opinion, everything that isn’t declared locally should have a prefix of some sort.