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):
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.
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:
- 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. - 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. - 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 namespacestd
, 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 namespacensb
must be looked up on thensa
namespacensc
must be looked up on thensb
namespacensd
must be looked up on thensc
namespaceclass_x
must be looked up on thensd
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 thensa
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 namespacestd
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
Error: Cannot Convert 'Const Wchar_T [13]' to 'Lpcstr {Aka Const Char*}' in Assignment
Addition of Two Pointers in C or C++ Not Supported. Why
How Serious Is the New/Delete Operator Mismatch Error
Invalid Initialization of Non-Const Reference with C++11 Thread
Does Copy List Initialization Invoke Copy Ctor Conceptually
Efficiently Convert Between Hex, Binary, and Decimal in C/C++
Glut Deprecation in MAC Osx 10.9, Ide: Qt Creator
Segmentation Fault with Char Array and Pointer in C on Linux
Why Can't I Access a Protected Member from an Instance of a Derived Class
Why Doesn't the C++11 'Auto' Keyword Work for Static Members
How Could Comma Separated Initialization Such as in Eigen Be Possibly Implemented in C++
How to Tell Pyximport to Use the Cython --Cplus Option
What's the Real Reason to Not Use the Eof Bit as Our Stream Extraction Condition
Can't Compile Easy Source in C++ and Opengl (Glfw) in Linux in Netbeans
What Is the Purpose of a Declaration Like Int (X); or Int (X) = 10;