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

1

28

Why is adding names to the std namespace undefined behaviour?

The obvious answer is "because the standard says so," e.g. in C++14 [namespace.std] 17.6.4.2.1/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. ...

However, I would be really interested in the reasons for this ruling. I can of course understand adding overloads of names already in std could break behaviour; but why is adding new, unrelated names a problem?

Programs can already wreak havoc inside std with macros, which is why pretty much all standard library implementations have to consist solely of reserved names (double-underscore and starting-underscore-followed-by-capital) for all non-public parts.

I would really be interested in a situation in which something like this can be problematic:

namespace std
{
  int foo(int i)
  { return i * 42; }
}

#include <algorithm>  // or one or more other standard library headers

when this is perfectly legal and the standard library has to cope:

#define foo %%

#include <algorithm>  // or one or more other standard library headers

What is the rationale for this Undefined Behaviour?

Pretorius answered 31/5, 2016 at 8:49 Comment(9)
Maybe because any specific implementation of std might have undocumented things in it, that might interact with things that you'd put in std yourself (for example, you might be defining something with a name that already exists, and then the standard can't guarantee that everything works as specified anymore).Sheikh
@Sheikh That's what I tried to address with the macro bit - it's still perfectly legal for me to define a macro with any non-reserved name. How does this "std with with an undocumented std::x" cope with me doing #define x %%%?Pretorius
@Sheikh shouldn't it be covered by trailing underscores in labels?Selfheal
What if you decide that you need a vector::random_iterator, you add it to std, and in the next version the wise people who make these decisions think: "Hey, let's add a vector::random_iterator" and make array_shuffle use it.Sanburn
My simplistic thought would be that the idea of the std namespace is to standardize things, so allowing you to change it would rather defeat the point.Unshackle
@Angew How about "A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header"? (C++11, 17.6.4.3.1). (It's not limited to documented names.)Gaur
@sleeptightpupper: actually, the standard does prohibit you from defining any of the reserved names in any shape or form. All language keywords and all names used in the standard C++ library (and a couple of generic names) are reserved.Norvin
@Gaur It's technically not limited to documented names, but does that mean that you have to parse all of your standard library headers and find all non-public names in there before you can legally define a macro?Pretorius
Would there have any problem with a rule which said that extending the std:: namespace in any way inconsistent with what a future C++ spec does would be UB? That would allow people to adapt code written for future C++ specs by adding features to std:: that match what the new spec will implement, while also allowing compilers to add features from the new spec while still supporting the old one.Swop
G
13

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.
Grisons answered 31/5, 2016 at 9:20 Comment(6)
Excellent point about the implementation source files: I believe that's precisely the thing I overlooked.Pretorius
Though this doesn't affect the behavior of programs, an implementation may choose to take the standard literally. For example, libstdc++ names one of its variables Container c because that's what it says in the standard, though you'd normally expect it to be uglified.Starks
@sleeptightpupper: I don't think any of the exposition only things in the standard library result in reserving names. There is probably no formal specification but I consider these declarations non-normative and, thus, the names not to be reserved. The relevant clause (17.5.2.3, [objects.within.classes]) doesn't state that explicitly but I think it is implicit in the first paragraph.Norvin
@sleeptightpupper We are talking about the container adaptors, yes? Those are protected members, so the name is part of the interface.Nix
unless otherwise specified... en.cppreference.com/w/cpp/language/extending_stdMarbleize
@DietmarKühl: I do not agree with point 3. I have an example where I have to put a name into std. See my question.Hautesalpes

© 2022 - 2024 — McMap. All rights reserved.