7

Why are some parts of the C++ standard library (and it seems like in more recent standards it is getting more common) not directly in the ::std namespace, but rather in a nested namespace? std::chrono and std::filesystem are two examples that pop to mind.

Baruch
  • 20,590
  • 28
  • 126
  • 201
  • 1
    It's done to categorize the elements of the standard namespace i.e. `std::chrono::duration` is of course specific to timekeeping. This is also nothing too new. Consider `std::string::npos` for example. – Justin Randall Jan 18 '18 at 15:13
  • 5
    @JustinRandall: `std::string::npos` is not a namespace. And your example does not answer the question. Vectors are specific to containers, so why isn't there a `std::container` namespace? – Christian Hackl Jan 18 '18 at 15:15
  • 2
    To those voting to close as opinion-based: Let me just point out that I did not ask for a discussion on the pros and cons of putting things in nested namespaces, I asked why this was done in these cases, which should be a fact-based question for anyone that was involved with or heard from whoever made this decision. If other people are suggesting their educated guesses (which I am all for) that does not make the question opinion-based – Baruch Jan 18 '18 at 15:48
  • This question can be answered with facts; it should not be closed just because most answers so far have been largely opinion-based. Voting to reopen. – Christian Hackl Jan 18 '18 at 15:52
  • @ChristianHackl I also voted to reopen because the "put on hold as primarily opionion-based" was primaryily based on opinion without fact support :)... recursively – Oliv Jan 18 '18 at 15:59
  • 1
    Re: `std::chrono`: https://stackoverflow.com/a/13442036/576911 – Howard Hinnant Jan 21 '18 at 14:41

3 Answers3

10

The obvious reason is the same as for any other project: there would be name collisions without it. For example, std::filesystem::copy vs. std::copy.

This isn't a complete explanation though, because

  • I can't immediately see any collisions in the std::chrono namespace
  • the committee could just have chosen a non-conflicting name instead

More convincingly,

  1. these libraries are based on their Boost predecessors, because those have proved to be useful and are well-tested. That means there's existing code using them, and it's easier to port that code to the C++11 versions if the namespace structure doesn't change, and no new conflicts are introduced.
  2. more broadly, C++ best practice has evolved since the first version of the standard library.

Note that (as Default points out in a comment), the regex library chooses consistency with Boost over namespace best practice, so it seems like #1 is more important. The same is true for std::thread etc.


Separating the factual from the speculative and hypothetical:

  • The discussed libraries are based on Boost predecessors
  • The discussed libraries keep the namespace structure of their Boost predecessors
  • The discussed libraries' namespace structures are not consistent among themselves (or with the rest of the standard library)
  • Changing namespace structure in C++, even without name collisions, can have side-effects related to ADL (so it isn't a trivial search-and-replace)

Conclusion: the namespace structure was chosen for consistency with Boost, rather than consistency with the rest of the standard library or even among the libraries added in C++11.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • Didn't think of the connection to Boost, which makes sense from a practical point of view but honestly I'm not sure it justifies the lack of consistence... If you can run `sed -e 's/boost::/std::/g'` you can run `sed -e 's/boost::regex_/std::regex::/g'`... – jdehesa Jan 18 '18 at 15:30
  • 1
    @jdehesa: changing namespace structure might introduce bugs (with ADL). – Jarod42 Jan 18 '18 at 15:33
  • 1
    You're missing an important point here, *user code*! `chrono` contains commonly used names such as `duration` or `hours`. Putting them directly in `std` would have likely caused name collisions or ambiguities with pre-C++-11 code doing `using namespace std;`. (I'm not going to discuss the relative merits of doing or not doing `using namespace std;` here… this is just about likely committee reasoning.) – Arne Vogel Jan 18 '18 at 16:32
  • @ArneVogel: And if you have pre-C++11 code with `using namespace std;` and `struct thread;`? – Christian Hackl Jan 18 '18 at 16:37
  • I am accepting this answer since no answer has been posted with actual facts ("I was on the committee and this is why we did it ...") and this is the only one with what seems to be pretty good evidence in it's favor. – Baruch Jan 21 '18 at 11:05
0

Having multiple namespaces minimizes the chance of aliasing problems. Everything from the standard library must be within std::, ok, but the standard library is still quite big for a single namespace. For example, in std::filesystem you have the function std::filesystem::status. It is easy to imagine other parts of the library where a status function may be needed at some point. And the namespace also makes clearer the purpose or "domain" of the function when reading the code.

Also, if you are, for example, using namespace std; at some point in your code, you may have some status function yourself in the current namespace so this allows you to avoid repeating std:: without pulling every single thing from the standard library directly into your local namespace, or more selectively pick the specific subset of names that you want to bring in.

That said, breaking down an API into uncountable namespaces is not too practical either. Maybe someone more familiar with the C++ standarization process can give a more complete answer with details about how does the committee decide when to add a namespace, but in the end is a matter of design and style, and there are no unequivocal, unquestionable rules.

jdehesa
  • 58,456
  • 7
  • 77
  • 121
  • or it could be written `filesystem_status` as they did for [`regex_match`](http://en.cppreference.com/w/cpp/regex/regex_match). – default Jan 18 '18 at 15:21
  • @Default Yes, that's why I added the last paragraph... To be honest I think that could have been a namespace, for example [`std::sub_match`](http://en.cppreference.com/w/cpp/regex/sub_match) does not even have `regex` in the name and I don't think it's immediately obvious it is about regular expressions. But then again what do I know, I imagine that being the result of dilated discussions within the committee... – jdehesa Jan 18 '18 at 15:26
0

Consider std::filesystem::absolute.

Without filesystem subnamespace this function should have been named something like std::filesystem_absolute. This is viable approach but is less flexible than one with a subnamespace. Remember that you can use Namespace aliases.

it seems like in more recent standards it is getting more common

I think this is the case because standard library is getting more and more large.

ks1322
  • 33,961
  • 14
  • 109
  • 164