-1

The fact that the std namespace is reserved for the standard library does not stop anybody from adding functions to it in one's personal code. Such additions will not become parts of the standard library, of course, but they can be done.

For example, Extending the namespace std - Program-defined types says:

It is undefined behavior to add declarations or definitions to namespace std or to any namespace nested within std, with a few exceptions noted below

...

Program-defined types
...
Program-defined types are non-closure class types or enumeration types that are not part of the C++ standard library and not defined by the implementation, or closure type of non-implementation-provided lambda expressions (since C++11), or instantiation of program-defined specializations.

In the example below, I am adding an overload of function std::to_string() for a program-defined type C:

// tested with gcc-11.2.0
#include <iostream>
#include <string>

// some custom class
struct C { int b; float c; };

namespace std {
    std::string to_string(const C & c) 
    { return "I am: "+std::to_string(c.b)+' '+std::to_string(c.c); }
}

int main(void) {
    C c; c.b = 3; c.c = 4.4;
    std::cout<<std::to_string(c)<<std::endl;
}

Output:

I am: 3 4.400000

Is what I am doing here illegal from the C++ standard point of view (and I am only able to do it due to an oversight of GCC developers)? Or, is this just an example of code, which many people would consider as a potentially dangerous idea, which is better to avoid?

I am not an expert in C++ seeking an expert opinion.

Update:

Here is what my conclusion is from the expressed opinions. Technically, adding code to the std namespace can break it since there is a chance that one can change behavior of the code through collisions with the names used to implement it. However, that does not mean that it should not be done if one knows what he/she is doing and has good reasons. Examples:

  • One is doing research on the next C++ standard and the only way to test the ideas is to add tons of new code to std and check how all the new code fits together and if it collides with anything in the previous version(s) of the standard.
  • One works on high frequency trading code and came up with a clever idea of how to hack the hell out of the code in std to shave off precious nanoseconds in latency, maybe even at the cost of intentionally breaking some of the functionality, and make millions of dollars of additional income. By all means, do it and laugh all the way down to the bank at all the people who wrote "legal" C++ and lost money to you as a result.
  • One works in computational genetics or high energy physics, and uses C++ to do complex processing of large amounts of data. This person uses class names involving biology or physics terms, which he knows have no chance in hell to collide with anything in std. He also knows that his government research funding agency and 99.9% of his research competitors do not give a rat's brownie about C++ standards. He has a sharp deadline to submit his next research funding proposal or to finish a paper or a new data analysis for a conference presentation. And if it helps to save time and have the essential work done by adding something to std, do not screw your career - do what you need to do.
S.V
  • 2,149
  • 2
  • 18
  • 41
  • One's personal code just broke a contract with the implementation. Any strange errors or misbehavior are not the fault the library anymore. `std::string to_string(const C & c)` **is not** a specialization, it's an overload. – StoryTeller - Unslander Monica Oct 22 '21 at 21:23
  • Did you notice, in your link, the mention of **template specializations**? That page states that you may write certain template specializations with "program-defined types". Your `to_string` is not a template specialization, and therefore Undefined Behavior. – Drew Dormann Oct 22 '21 at 21:26
  • 1
    One way this can break is if there is a name `C` in the `std::` namespace. Then the `C &c` parameter would be that type, instead of your (global) `C`. This could be avoided by using `::C`, but that would not resolve all potential problems. One way to avoid these issues is to define your `to_string` in the `::` (global) namespace, add a `using std::to_string;` after it, then just use `to_string` in your `main`. – 1201ProgramAlarm Oct 22 '21 at 21:32
  • @DrewDormann My link says _"Program-defined types"_ **or** _"enumeration types that are not part of the C++ standard library and not defined by the implementation"_ **or** _"non-implementation-provided lambda expressions"_ **or** _"program-defined specializations"_, so my reading it is that it is OK to do, if one knows details of _"implementation"_ (to avoid collisions with any names in `std`, including implementation details). Such code might, of course, work fine in one implementation, but not in some other. – S.V Oct 22 '21 at 21:38
  • It may not work in a new version of the same implementation too, so there's more than just the "which implementation" axis. – StoryTeller - Unslander Monica Oct 22 '21 at 21:40
  • @S.V you are quoting the **definition** of "Program-defined types", and skipping over **where** those program-defined types can be used. The page says that program-defined types, like what you list, may be used in specific _template specializations_. – Drew Dormann Oct 22 '21 at 21:46
  • @DrewDormann It is not how I read the page (which does have unfortunate formatting of sections). The section I am quoting is not a part of "Adding template specializations" and is a separate section. Plus, I am not asking about what the web-site says. **I am asking if it is legal to do according to the C++ standard**, not according to any specific web-site. – S.V Oct 22 '21 at 22:00
  • It is not. For the reasons I gave. – Drew Dormann Oct 23 '21 at 01:53
  • @S.V "illegal" or more specifically Undefined Behavior in this case does not necessarily mean "compiler should be rejecting the code". It only means the C++ standard washes its hands of the consequences. You can write as much code exhibiting Undefined Behavior as you want as long as you accept the consequence, including other professionals refusing to help you because there's no way to guarantee that recommendations will work. –  Oct 25 '21 at 17:14
  • And regarding points 2 and 3 of your update: In my experience whenever one of these things are argued, 99.99% of the time they are said to excuse laziness. There is almost always equivalent valid C++ code that accomplishes the same thing. –  Oct 25 '21 at 17:22
  • @Frank Yes, of course, you are right and I understand now what the rules of the game are. Thank you to everybody for clarifying them for me! – S.V Oct 25 '21 at 17:24
  • @S.V. FWIW, in the case of the code you posted, I would go about it like this: https://gcc.godbolt.org/ –  Oct 25 '21 at 17:34

1 Answers1

1

Yes, it is undefined behavior to add names to std except for explicit specializations, and your to_string is not the one. And yes, almost all the time you will see the program behaving as expected.

The main reason to introduce the rule is to give implementors a leeway into putting non-transparent names into std. Such names could collide with yours if you were to to also put them in std, and this rule prevents this from happening.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • some tips on what to do instead would be nice – sp2danny Oct 22 '21 at 21:36
  • @sp2danny depends on what one's goals are. May be the simple answer to "what to do instead" question is just "use a different namespace", or may be it is something else. – SergeyA Oct 25 '21 at 14:54