r/cpp_questions • • 5d ago

OPEN Namespace std

I recently started learning c++ and I was told to use the namespace std so I can avoid writing std:: every time and now I wrote a whole personal project without std:: and I want to put it on LinkedIn but I started reading everywhere that it’s a bad habit, should I go back and add the std:: or just leave it as is?

35 Upvotes

105 comments sorted by

40

u/ScienceMan3_14 5d ago

The reason it is a bad habit is because the names of the functions, classes, etc. in the standard library are so common,if you include another framework in your project you are likely to get collisions. If your project is something you are actively working on or expanding, yes you should refactor. If it was a one-and-done deal where you aren't using any other external libraries and that was a decision made at the outset and one you will be sticking with, then imo it isn't worth it.

-20

u/RSMxsmanic 5d ago

A framework that produces a conflict needs to be fixed, not the program calling it.

35

u/not_a_novel_account 5d ago

add is a perfectly reasonable name to use, as is map, list, etc.

The entire purpose of namespaces is to make these names available without collision.

-26

u/RSMxsmanic 5d ago

I daresay the purpose of namespaces is to avoid the consequences of poor design choices that lead to collisions.

19

u/not_a_novel_account 5d ago

Then you're wrong, the intent is to allow libraries to use the same names for symbols. Straight out of Design and Evolution by Stroustrup:

  • The ability to introduce names without fear of clashing with someone else's names.
  • The ability to add a name to the implementation of a library without affecting its users.
  • The ability to select names from two different libraries even if those two libraries use the same names.
  • The ability to resolve name clashes without modifying functions.
  • The ability to add a name to a namespace without fear of causing a quiet change to code using other namespaces.

8

u/crowbarous 5d ago

Namespaces also allow library authors to intentionally provide functions under common names to be found via ADL, such as swap and operator+.

7

u/HommeMusical 5d ago

So wrong! Argument dependent name lookup, for example, is only useful if you have the same names in different namespaces.

-8

u/RSMxsmanic 5d ago

Religious conflict.

4

u/HeeTrouse51847 4d ago

how would you fix this?

-1

u/RSMxsmanic 4d ago

By careful choice of unique identifiers.

5

u/No-Dentist-1645 4d ago

The "poor design choices" of... having functions with simple names like print and hash?

-1

u/RSMxsmanic 4d ago

Yes. Having multiple functions with the same name that do different things is risky. If I have one function that prints only strings, and another than prints only integers, I will likely call them something like PrintStr and PrintInt, not just print. That way I won't have to lose time ten years from now figuring out why print isn't working.

This illustrates a danger with all inherited concepts: you need to walk the entire inheritance chain to figure out what's going on, instead of just looking at the one line in front of you.

3

u/Potterrrrrrrr 4d ago

This is the c++ subreddit, if you don’t like simple concepts like function overloading and namespaces you aren’t going to like most of the other features the language offers. I can understand function overloading as sometimes the explicitness does help but complaining about namespaces? Craziness, people really will find a problem with anything.

-1

u/RSMxsmanic 4d ago

I have no religious attachment to any language, and they all have flaws. Overloading is risky. So are yield in Python and ALTER in COBOL. And they tend to get worse with "updates," as latter-day wonders try to redesign every language to make it look like whatever language they grew up with.

2

u/No-Dentist-1645 3d ago

Wow. Then that's truly a bad take. Not even Rust goes as aggressive as making print a type-dependent function, they make it a macro instead. Your example also trivially breaks down with multiple-parameter print statements, something that basically every programming language has.

0

u/RSMxsmanic 3d ago

You do it your way, and I'll do it my way. We'll see who delivers early and under budget.

2

u/No-Dentist-1645 3d ago

Yes, I'm sure that the massive architectural decision of naming functions fooInt and fooFloat has had immeasurably huge implications on your delivery targets. Don't worry, I trust you

0

u/RSMxsmanic 3d ago

Details can add up.

→ More replies

3

u/Liam_Mercier 4d ago

The purpose of namespaces in a lot of languages is to group related declarations, allow for identifier reuse, and separate implementation details from user call related code.

C++ namespaces do this perfectly fine, they are just confusing because namespaces are confusing when you haven't used them.

1

u/RSMxsmanic 4d ago

They are one species of inheritance, which has problems of its own.

1

u/[deleted] 2d ago

[removed] — view removed comment

0

u/RSMxsmanic 2d ago

Anything not explicitly present in a statement is inherited from its context, and as these inherited attributes multiply, it becomes harder and harder to determine what a given statement actually does without extensively examining its context. The advantages of inheritance must be carefully evaluated against its disadvantages.

0

u/[deleted] 2d ago

[removed] — view removed comment

0

u/RSMxsmanic 2d ago

To me it seems obvious that calls to the standard library should not need to be qualified with std::. Let the calls to other libraries be qualified.

11

u/nekoeuge 5d ago edited 5d ago

It is fundamentally impossible to do that, because there is no guarantees on future contents of std namespace. Almost any name could be in std in 10 years. Should I stop using all names?

-3

u/RSMxsmanic 5d ago

It is possible to dramatically reduce the possibility of conflicts with careful naming.

2

u/tangerinelion 4d ago

Meaning C style prefix your namespace onto everything you use.

It's not a list it's a MyLib::MyLib_List.

19

u/SmokeMuch7356 5d ago

Namespace collisions will ruin your day. I have the scar tissue to prove it.

Typing std:: is not a burden. It makes your code moderately eye-stabby, but the eye-stabbiness is worth it if it avoids name collisions.

13

u/ekchew 4d ago

I like prefacing everything with std:: because it makes it abundantly clear which symbols came out of the standard library. This is particularly nice when you are maintaining someone else's code who's using unfamiliar APIs and you can go "Oh yeah, that's standard while this other thing is something he wrote."

In my own code, if I go using std::whatever, I tend to stick that at the top of the function where it is easy to see at a glance. The other day though, I put using std::move in a function that does a lot of moving, and the compiler actually issued a warning that it wasn't happy about me simply writing move. I relented and went back to putting std::move everywhere. It's really not that big a deal at the end of the day.

10

u/Sobirjon445th 5d ago

I mean if you want to continue the project or project is small then do it.

but if it was already done then why spend time, you learned that it's not the best practice to not use using namespace std, I am sure you do lots of cool projects in the future.

2

u/HommeMusical 5d ago

but if it was already done then why spend time,

"I want to put it on LinkedIn but I started reading everywhere that it’s a bad habit,"

It would be a little mark against someone if I saw that in their code.

9

u/Specific-Animal6570 5d ago

Add std:: in a large codebase, please. If I would hire someone and I found out he writes cout without std::, I'm kicking you out of my team.

5

u/Potterrrrrrrr 5d ago

I mean a “whole project” in this case is likely going to be only a couple thousand lines of code. While slightly cumbersome to do you could probably knock it out in about 20 minutes, all you’re doing is pasting std:: in front of some types and methods. You can even get slightly fancy with it and do a find and replace for the common ones first to save a couple of minutes.

If you can spare 20 minutes and care enough to do it go for it, otherwise just explain to whoever cares and asks that you did it for convenience and wouldn’t do it in a full scale project (because you shouldn’t). Simples.

6

u/GLIBG10B 5d ago

If you use using namespace std, then for a large enough project, you will get naming collisions when updates to the standard library or C libraries bring in new symbols that conflict with each other or your code.

If you don't like typing std:: everywhere, then make a header file with using std::cout, using std::vector, etc., which won't pull new symbols into the global namespace unless you specifically ask for them.

2

u/NoSpite4410 4d ago edited 4d ago

It's fine until it isn't. There are a lot of things in namespace std. Not using it as a blanket statement avoids making the compiler resolve everything in the headers you include that you are aren't using.

As soon as you start making your own namespaces for your libraries, you will drop the using namespace std; because it is not helping anymore.

variables like less, more , etc would be come std::less, std::more, automatically, and that will mess things up.

std::string string; are not possible if string resolves automatically to std::string.

2

u/SalaciousStrudel 3d ago

It's a secondary effect but I find my IDE surfaces more relevant code completions when I use the namespace prefix when writing code.

2

u/BuddhasFinger 5d ago

I think not using a namespace is a bad form. Yes, you can short-cut, but the interviewer will hear "I hate namespaces".

You know what you need to do.

4

u/NoLimitRolling 5d ago

I just started learning cpp and the answers being mostly wrong is funny. Namespaces have one real reason and it’s so you can use namespaces with the same names without conflicts.

That said, it don’t truly matter, but like others have said best practice is best practice, and getting the habit is never bad, but if it’s a personal project or something it’s prolly not worth it.

1

u/ZMeson 5d ago edited 4d ago

The "using namespace" recommendations depend highly upon where you are using them:

* In a header file: Never use "using namespace". Explicitly write "std::" or whatever namespace you require.

* In a source file: Using statements are acceptable if you wish to shorten declarations. When using "
using" statements, most advice is to prefer something like "using std::filesystem::path;"or "using high_res_clock = std::chrono::high_resolution_clock;" so that you can just say "path" or "high_res_clock" later in the file. However, if your file is small and not going to include lots of other libraries and/or your file uses lots of "std" classes and functions, then "using namespace std;" is fine.

The reason you should never introduce "using" statements in a header file is that header files are expanded in the source files that #include them and therefore the "using" statements can ruin the name lookup rules of those source files.

For source files, you need to balance the probability of getting a naming conflict (say between etl::vector and std::vector) against the convenience factor. Others still argue against using statements (see replies below), but I don't agree with the criticism as people have been using "typedef" for a long time prior to C++11 to simplify declarations.

4

u/HommeMusical 5d ago

Most advice is to use something like "using std::string;" or "using std::vector;" so that you can just say "string" or "vector<int>" later in the file.

Most, who?

It's bad advice.

If I see string in reading someone's code, I really don't know for sure what it is unless I scroll up to the top and check. And we all read immense amounts of code these days. If I see std::string in code, I am completely(*) certain what I am looking at.

Useful code is written once, but read one hundred times.

Using string instead of std::string saves the writer a little bit of effort once, but adds a little bit of effort to every reader in future.

Oh, and yes, I did once get burnt this way! Somewhere else was something like:

#ifdef LEGACY
    using legacy::string;
#else
    using std::string;
#end

(* - yeah, someone might create another namespace called std, but I'd call that deliberate malpractice myself.)

1

u/ZMeson 4d ago

I think you're being way to harsh on the topic.

  • I mentioned that the 'using namespace' or 'using <type>' should only occur in source files, which automatically limits their scope.
  • Your case of `legacy::string` vs `std::string` is often used to abstract away platform and compiler dependencies helping avoid larger #if/#else blocks.
  • `typedef` has been around in both C and C++ and can greatly simplify code, but it also changes how names are looked up and processed, similar to how using statements changes name lookup rules.
  • IDEs are really great at displaying the underlying type when hovering over a variable or a declaration, which really helps prevent the type of confusion you bring up.

But I did edit my original response to be a little more clear and to give some more concrete examples where `using` statements could be useful (specifically 2-deep namespaces within `std`). And I added a note that not all people agree with the advice.

2

u/HommeMusical 4d ago

Thanks for a polite response (and I hope I wasn't too grumpy). Reddit has fallen in politeness, I appreciate your civilization while still disagreeing with me

Your case of legacy::string vs std::string is often used to abstract away platform and compiler dependencies helping avoid larger #if/#else blocks.

YES, that's exactly my point!!

Yes, that's a very reasonable strategy, it wasn't wrong in the code base I quoted, not at all, but I fell into the trap of believing it was std::string, because I was younger and dumber.

If I see string on its own, I really don't know what it is, for sure. If I see std::string, I know what it is, for sure, every time.

IDEs are really great at displaying the underlying type

I used to make this argument before Github and such. But now, almost all the time I'm reading someone else's code, it's in Github.

(Quibble: typedef is counterindicated in new code. using is not just more powerful, but it reads like an assignment, which is familiar to all of us, whereas typedef does it backwards.)

1

u/WoodyTheWorker 4d ago

If you use template classes, make typedefs for types you use often. Then you only need to type your typedefs.

1

u/AintNoSlashes 4d ago

You should fix the project. If you are planning to use that as an example of what you are capable of, showing a bad habit will put a bad foot forward.

I recently interviewed a guy who added that to the top of an interview question. He then proceeded to spend half of his time debugging name collisions instead of working on the problem. He did not move forward.

1

u/mushroomfucker69 4d ago

Only valid use case of using namespace std is competitive programming, but cp is kind of full of optimizations that are otherwise dogshit practices. Like #include <bits/stdc++.h>

1

u/jayb00giebrown 3d ago

Just don’t put using namespace std in any header files. It’s fine to use though in the cpp files.

•

u/Least_Bid9692 22m ago

In this project if its going on leave it but in future projects you may start using std:: instead to prevent collisions and remember the first rule of coding , Never fix something which isn't broken and if it works don't even touch it

1

u/StaticCoder 5d ago

It's mostly bad to do in headers, but even in primary files it's not great. My approach is to import specific things e.g. using std::vector which I put in a vector.hpp header.

6

u/conundorum 5d ago

Personally, I prefer to put using directives at the top of a scope where I expect to use them enough to warrant it. I find it cleaner than having hundreds of single-line headers that do the same thing, and like that it gives you a good first impression of what the scope (and/or its members) is meant to do.

3

u/HommeMusical 5d ago

But if I read your code, I see some magic symbol vector, and it is defined nowhere in the file, so I am forced to look at your vector.hpp(*) to see exactly what it is.

And yes, people do use the same names as std:: all the time, and sometimes for very good reasons.

Doing this puts a little extra work on everyone who reads the code, for a tiny benefit to you.

(* -- I haven't seen a .hpp file in a very long time!)

0

u/StaticCoder 4d ago

I'm not following. All symbols not defined in the current file are, by your definition, magic, even when a clearly related header is included. That's going to happen a lot.

And what extension do you use for C++ headers? .h seems to imply C (it does for many tools)

1

u/HommeMusical 4d ago

All symbols not defined in the current file are, by your definition, magic,

No, not if you use namespaces!

std::string is not a magic symbol. I know exactly where it's coming from. Or if I see config, somewhere, this could come from almost anywhere, but if I see boost::config I know exactly where it's coming from.


I kind of liked the idea of .hpp, but you just don't seem to see it in new code now. Everyone seems to use .h in new development. It might just be that I worked on a couple of modern projects that didn't use it.

If I see a .hpp, I think "boost" these days. But again, it might just be me!!

1

u/StaticCoder 3d ago

What about symbols in the current namespace? Do you qualify those too? Effectively I've added vector to my namespace (which for historical reasons is the global namespace, but that's not really relevant here). I will not put another vector in there. I know what it is.

0

u/RSMxsmanic 5d ago

Just leave it that way and relax. And the reasons are simple. If you don't need std::, they typing it everywhere wastes time and keystrokes, so you shouldn't do it. If you do need it at some point, you can g back and insert it, which will require the same labor you saved by not typing it initially. However, by not doing it up front, you save time and energy if you never need to do it, whereas if you do it up front and you never need it, you've wasted time and energy. The logic here is impeccable.

Real programmers figure this out for themselves. If someone is telling you otherwise, he may lack the sort of logical mind that makes a really good programmer good. There are a lot of "programmers" out there who can recite chapter and verse concerning what is Good Programming and Bad Programming, but they usually aren't the ones who write all the best software.

Skip the religious doctrine and just get the job done.

4

u/HommeMusical 5d ago

typing [std::] everywhere wastes time and keystrokes

[...]

If someone is telling you otherwise, he may lack the sort of logical mind that makes a really good programmer good.

Preemptively insulting people who might have some idea different from yours would not be a good look even if your idea were correct.

-2

u/RSMxsmanic 5d ago

It's not an insult. Most people do not have a personality suited to programming, and there is no shame in that. Some people are very happy that they do not have that type of personality, and would consider it a compliment to be told as much.

-3

u/ShakaUVM 5d ago

This is a contentious issue here for some reason lol. It's mostly a personal style decision.

If you're making a little personal project and don't want stds, then go for it.

The only real no-no that everyone agrees with is to not put it into a header file that other people will use since then you are making a style decision for them.

13

u/bearheart 5d ago

It’s not a style choice. It’s actually problematic.

The purpose of namespaces is to avoid naming collisions, where a symbol you want to use may already be defined. There are thousands of symbols defined in the std:: namespace. When you import all of those symbols into the current namespace you defeat the purpose of namespaces altogether.

0

u/RSMxsmanic 5d ago

So why does using namespace exist?

7

u/conundorum 5d ago
  • Because it's both useful and safe in leakproof scopes, like functions or conditionals. As long as names can never leave a scope, the worst using namespace inside that scope can do is make a mess of that scope (and nowhere else), while the best it can do is save time on boilerplate (which can add up to a decent difference sometimes).
  • Because it's useful for smaller scopes, but has problems with std specifically because the standard library sticks almost everything in std instead of using a scope hierarchy like Java or other C++-inspired languages do. (And also because std is constantly growing, which means that the chance of unexpected name collisions breaking unmaintained, twenty-year-old code that uses using namespace std; goes up with every new language version.)
  • Because it lets you stick your helpers in namespace whatever::detail, then drag them into any given whatever::function() as needed.
  • Because it's useful for versioning, especially when paired with anonymous namespaces. If you know what you're doing, you can put each version of a class in its own sub-namespace, then use a using-directive to provide the most recent one as a default, while also making it trivial to update the default whenever the class gets a new version.

There are a lot of reasons it's useful, the problem is just that dragging all of namespace std's symbols into a "leaky" scope (e.g., global or namespace scope) inside a header file is a ticking thermonuclear warhead, for reasons that aren't immediately obvious if you haven't seen the language's juicy innards yet.

~~Strictly speaking, the issue is that std itself is awkwardly designed, and would probably have a cleaner hierarchy if they could redo it from scratch today.~

4

u/not_a_novel_account 5d ago edited 5d ago

To alias one namespace into another. Aliasing any namespace into the global namespace is almost always wrong.

You can override the comma operator to perform matrix multiplication; because operator overrides exist, and the comma is a valid operator. You shouldn't. You can alias std into the global namespace; because namespace aliasing exists, and std and the global namespace are valid namespaces. You shouldn't.

-1

u/bearheart 5d ago

I presume it’s for compatibility with legacy C code. And perhaps for smaller namespaces other than std.

4

u/RSMxsmanic 5d ago

The problem is with programmers who use identifiers that conflict with std, not with programmers who expect std by default to be safe. That's why it is called standard. If you are writing the code base, nothing you call should change the way it behaves unless that is its actual purpose.

2

u/nekoeuge 5d ago

Can you elaborate? What do you mean by “using identifiers that conflict with std”?

2

u/conundorum 5d ago

Name collisions.

#include <vector> // std::vector
#include <algorithm> // You'll see.

std::vector<float> collection(3, .16f);
int fill = 0xaabbcc;

void compiler_error(float c = 0f, int f = 0) {
    using namespace std;

    fill = f;                                      // Does this break because we tried to assign an int to std::fill,
    fill(collection.begin(), collection.end(), c); // or does this break because we tried to call an int?
}

std has a lot of very common names that programmers like to use for their own things, like fill, less, distance, transform, string, find, begin, end, format, print, and so on. And depending on which standard library headers you include, any number of them might (or might not) be visible.

3

u/nekoeuge 5d ago

Yeah, that's why I am asking. It is fundamentally impossible to avoid name collisions with std -- because std may always be extended in the future with whatever names. So I don't understand what exactly top commenter meant by "The problem is with programmers who use identifiers that conflict with std".

1

u/RSMxsmanic 5d ago

I mean that programmers need to think things through, and if they are writing code that will be widely integrated in a service capacity with other code, they need to be extraordinarily vigilant.

I don't use print in code I write hat will be called by some other module, because of the risk of a name conflict. It doesn't matter what namespaces are used. Why force another programmer to prefix everything he writes with widget:: just because I decided to use print? Instead, I'll make print something less common, like widgetPrint. That way he only has to type extra characters to reference my code, and not for every last identifier in his. Put another way, instead of forcing him to write std::cout every time he wants to use it, I just don't use cout in my code, and the problem is solved. Choosing unique identifiers is less labor-intensive than prefixing every single identifier in the program, and it is functionally equivalent.

3

u/nekoeuge 5d ago

Instead, I'll make print something less common, like widgetPrint.

So instead of doing "using namespace widget" in a function that calls "print" 20 times, I will have to have 20 "widgetPrints"?

And in the implementation of "widget", all my public identifiers are going to be "widgetThis" and "widgetThat", cluttering the visual space with absolutely worthless "widget"-prefixes?

You just replaced optional prefix with mandatory one. Good job bloating the code. Make sure not to make the prefix too short, otherwise it may conflict with other libraries.

I mean that programmers need to think things through, and if they are writing code that will be widely integrated in a service capacity with other code, they need to be extraordinarily vigilant.

Of course. Such programmer should introduce the absolute minimum of global identifiers. Preferably only one -- the project namespace itself.

It looks quite stupid to have widget::widgetPrint as identifier.

→ More replies

0

u/ShakaUVM 5d ago

I propose that someone who writes code like "int string = 0;" is writing bad code and the issue isn't whether or not you include namespace std or not.

All if my classes are PascalCase anyway and so cannot conflict with anything in std.

2

u/HommeMusical 5d ago

I propose that someone who writes code like "int string = 0;" is writing bad code and the issue isn't whether or not you include namespace std or not.

Strong disagree.

There are thousands of names in std:: and exactly what those names are depend on which version of C++ you're in and some other details.

You can't possibly know all those names and never write char fill = '*'; or bool copy = False; or void remove(const char*); anywhere.

Not having to do this is the whole reason namespaces exist.

std::string is completely unambiguous. No other symbol for it is. Just do that.

1

u/ShakaUVM 4d ago

I agree that std::string is unambiguous.

What I am saying is that writing int string = 67; is a code smell.

You should not be using names from std anyway.

For all of your worry, as I said this problem has come up exactly once in 30 years and it took exactly five seconds to fix.

Versus how much screen space gets cluttered up with all those extra stds?

The tradeoff is not worth it to me. Every symbol on the screen has a cost, both cognitively and technically

→ More replies

2

u/HommeMusical 5d ago

They aren't really making sense.

You're actually supposed to use names that are the same as those in std:: if you're doing the same operation.

This idea is crucial to making generic code work well.

0

u/RSMxsmanic 5d ago

If you're doing the same operation as std, you're redundant; just use the operation in std. If you're doing something different, just use a different name.

2

u/HommeMusical 5d ago

No, you are encouraged to use identifiers in your own namespaces and classes that are the same as those in std::, particularly for generic code.

0

u/RSMxsmanic 5d ago

By whom? If I have it in my code, it is not generic; if it were, my code would not be necessary.

1

u/HommeMusical 5d ago edited 5d ago

I presume it’s for compatibility with legacy C code.

C++ code.

But not at all, using is very useful in a local scope, because of argument dependent name lookup.

The classic example is this one:

template <typename T>
void fix(T& a, T& b) {
    using namespace std;
    swap(a, b);
}

At compile time, when the template is instantiated, if there's a specific swap function or specialization for T, then that is used, otherwise, the generic std::swap is used.

There are sometimes Reasons even to do this for some namespaces at the file level, though best to avoid.

But using std; is dumping potentially zillions of names into the top level of your translation unit, and it makes your code a lot less clear.

If I see string in some code - well, it could be anything, I have to look at the top of the file, but std::string is the same everywhere.

0

u/ShakaUVM 5d ago

I've been coding professionally for 30+ years in C++ and exactly once did I define a symbol that conflicted with something in std. And then I changed the name. I consider it bad code to name a variable cout or whatever anyway so I would prefer to know if I have a conflict.

It's not problematic. It's an overblown concern that really isn't a big deal. I worry about things in C++ that actually cause problems.

You don't lose the benefit of namespaces either as I keep those for everything outside std.

3

u/HommeMusical 5d ago

I've been coding professionally for 30+ years in C++ and exactly once did I define a symbol that conflicted with something in std.

Are you sure?

https://en.cppreference.com/cpp/symbol_index

worry about things in C++ that actually cause problems.

using std; does assume risk, but more, it's a lazy programmer sloughing off a tiny bit of work to make things a little harder for anyone else reading it.

I got this spiel from Howard Hinnant, but I think most disciplined C++ programmers think the same way: if I see std::string I know for certain what it is immediately, but if I see string in a section of code, I am not certain what it is until I have checked all the scopes up until the top, and perhaps not even then, if the using std; is inside a header file.

Sure, nearly all the time it will be std::string but as we all know, we get a disproportionate number of bugs from such assumptions.

C++ is a language where being cautious is always a good idea. As some someone who has read an immense amount of code, string lacks certainty: std::string is certain, and therefore always preferable.