C++ When Is It Ok to Extend the 'Std' Namespace

C++ When is it OK to extend the `std` namespace?

The only case where it is OK to add a definition into the std namespace is specialization of a template that already exists in the namespace and to explicitly instantiate a template. However, only if they depend on a user defined type.

[namespace.std] (standard draft):

  1. The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

  2. The behavior of a C++ program is undefined if it declares

    (2.1) an explicit specialization of any member function of a standard library class template, or

    (2.2) an explicit specialization of any member function template of a standard library class or class template, or

    (2.3) an explicit or partial specialization of any member class template of a standard library class or class template.

    A program may explicitly instantiate a template defined in the standard library only if the declaration depends on the name of a user-defined type and the instantiation meets the standard library requirements for the original template.


As an example of standard templates that are explicitly designed to be extended for user defined types: std::hash and std::iterator_traits.

Extending namespace std to implement make_unique when using C++11

No, this is forbidden—even though, via

#define make_unique ? ? ?

a conforming C++11 program can be quite sure that the library never mentions the name (outside of a stringization) and would thus be unable to detect the extension.

What are the reasons that extending the std namespace is considered undefined behavior?

Here are a few reasons:

  1. Even if names in headers have to be uglified to avoid interactions with macros, this requirement does not exist for name in the source files actually implementing the code. If an implementation does use ::std::foo(int) as part of its implementation it would be a violation of the one definition rule.
  2. The standard is expected to grow. If names could be added to namespace std any name added to the standard C++ library would be a likely breaking change. To some extent this is already true in the sense that any such name could be a macro but it is considered acceptable to break those.
  3. There is actually no need to add names to namespace std: they can be added to arbitrary other namespace, i.e., even if the motivations given above are not particular strong, the restriction isn't considered to matter in any form. ...and if there is a reason to add a name to namespace std, it clearly does affect the behavior.

Is it allowed to extend the std::numbers namespace with new definitions?

is it allowed to extend the std::numbers header to include the ones not already defined?

No, you may not add definitions to std namespace nor its subnamespaces (except for class template specialisations in cases where that isn't explicitly disallowed).

You can instead have them all in one place in your own namespace with using declartions:

namespace Casey
{
inline constexpr double missing_number = 123;

using std::numbers::e;
// ...
}

Instead of using each number individually, you could use using namespace std::numbers, but that has the caveat that future standard versions may add numbers whose names may potentially conflict with yours, breaking future compatibility of your header.

Why is using namespace std; considered bad practice?

Consider two libraries called Foo and Bar:

using namespace foo;
using namespace bar;

Everything works fine, and you can call Blah() from Foo and Quux() from Bar without problems. But one day you upgrade to a new version of Foo 2.0, which now offers a function called Quux(). Now you've got a conflict: Both Foo 2.0 and Bar import Quux() into your global namespace. This is going to take some effort to fix, especially if the function parameters happen to match.

If you had used foo::Blah() and bar::Quux(), then the introduction of foo::Quux() would have been a non-event.

Does `using namespace ...` increase compilation time or can it somehow affect performance?

tldr No, it doesn't affect neither compilation time nor run-time

Strictly speaking every change in the source code modifies the compilation time. Using directives, using statements and all forms of aliases don't affect compilation time in any meaningful or note-worthy way.

As for run-time performance the generate code is identical, so absolutely no performance impact whatsoever.

In conclusion don't worry about it, not in the slightest.


I would like to challenge Ayxan statement that the compilation time is is increased because the more places are considered during name lookup. I could argue the opposite: that compilation time is decreased because nested namespaces are looked up just once on the using directive, instead of on every qualified name.

Consider this:

auto x = nsa::nsb::nsc::nsd::class_x{};
auto y = nsa::nsb::nsc::nsd::class_y{};
auto z = nsa::nsb::nsc::nsd::class_z{};

vs

using namespace nsa::nsb::nsc::nsd;

auto x = class_x{};
auto y = class_y{};
auto z = class_z{};

In the first case:

  • nsa must be looked up on the global namespace
  • nsb must be looked up on the nsa namespace
  • nsc must be looked up on the nsb namespace
  • nsd must be looked up on the nsc namespace
  • class_x must be looked up on the nsd namespace
  • repeat all above thee times (for all the qualified items)

In the second case

  • just like before, look up nsa in the global namespace, nsb in the nsa etc. Except just once, during the using directive.
  • add entry in the table lookup for the using directive
  • look up class_x in the global namespace + the entries brought by the using directives. Do this for all the unqualified names.

I am not saying one is faster than the other. I am saying it's not as simple and black and white. Without a proper benchmark (study really as the codebases wildly differ) we don't know. Anyway, my point is that it doesn't matter anyway as any difference practically doesn't matter.

Adding types to the std namespace

No ... part of the point of a namespace is to prevent name collisions on upgrade.

If you add things to the std namespace, then your code might break with the next release of the library if they decide to add something with the same name.

extending namespace std via partial template specialization

You might mean [namespace.std]/1:

A program may add a template specialization for any standard library
template to namespace std only if the declaration depends on a
user-defined type and the specialization meets the standard library
requirements for the original template and is not explicitly
prohibited181.


181) Any library code that instantiates other library templates must be prepared to work adequately with any user-supplied
specialization that meets the minimum requirements of the Standard.

If partial specializations of function templates are ever introduced, this quote would also implicitly cover them (as it doesn't restrict itself on explicit specialization).



Related Topics



Leave a reply



Submit