8

This question is a follow-up question of this one.

Consider the following program:

#include <cmath>

// meaningless, only for language-lawyer purpose
void abs(void*) {}

int main(){
    abs(nullptr);
}

Does this program result in undefined behavior?


The related part in the standard is [extern.names]/4:

Each function signature from the C standard library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.

I'm not sure whether overloading is permitted.

xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • I don't know whether the behaviour is undefined, but it is certainly unexpected. – Henri Menke Jun 19 '18 at 09:57
  • That's a weird paragraph. It starts with signatures, which is quite clear, and then segues to names. – StoryTeller - Unslander Monica Jun 19 '18 at 10:03
  • 1
    @Ron `int abs(int);` is a *function signature from the C Standard library declared with external linkage*. The non-bold text says this signature is reserved; but then the bold part goes on to say that the signature is reserved as a name, which makes no sense – M.M Jun 19 '18 at 10:04
  • Some "functions" are sometimes implemented as marcos - `htons` for example. While not a "reserved" function that I know of, it highlights how poor some implementations can be. – UKMonkey Jun 19 '18 at 10:26
  • @UKMonkey: C++ specifically says the C names which can be implemented as functions or macros have to be functions in C++. However, `htons` is not a Standard C function, which is why it's not covered by that rule. – MSalters Jun 19 '18 at 10:29
  • Why would you **ever** want to do something like this? – Walter Jun 19 '18 at 11:10
  • @Walter there are a number of questions about overriding std::to_string() for custom objects I imagine this has similar motivations – UKMonkey Jun 19 '18 at 11:18
  • @UKMonkey **Nope**. This question is **not** about overloading any methods in `std`. So your example doesn't apply. – Walter Jun 20 '18 at 09:09
  • @Walter *Yup* If you seriously can't think of a function that would be of use to overload in global namespace, and you can't understand the word *"similar"* Then I don't see how you can say doesn't apply. Maybe you mean "I can't think of any similar examples - could you give me one"? – UKMonkey Jun 20 '18 at 09:15
  • @UKMonkey No, I cannot think about such a thing. A user should add **nothing** to the global namespace except `int main()`. All other stuff can happily live in an anonymous namespace. – Walter Jun 20 '18 at 09:18
  • @Walter Well don't ask questions if you don't want to know the answer then. – UKMonkey Jun 20 '18 at 09:19

2 Answers2

1

There are two parts to this statement, as it talks about names (from the C standard) that are reserved (for C++ implementations). In particular,

Part 1: Each function signature from the C standard library declared with external linkage

This includes the C library function abs

Part 2: is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage, or as a name of namespace scope in the global namespace.

So the name ::abs is reserved for the C++ implementation. You can't use it. Overloading is irrelevant.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 1
    If it means the name `::abs` is reserved, then all the un-bold text in the original quote would be redundant. Not saying you're wrong but there still seems to be some mystery about this paragraph. – M.M Jun 19 '18 at 10:51
  • @M.M: Names with "C" linkage don't live precisely in the global namespace, IIRC. – MSalters Jun 19 '18 at 11:00
  • 2
    `abs` is not a function signature, so cannot be referred to in Part 1. – Walter Jun 19 '18 at 11:05
  • @M.M The un-bold text brings the constraint into non-global namespace. [This](https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/qLaQUMHASIs) is a related discussion. – xskxzr Jun 20 '18 at 07:39
  • 1
    For some reason everyone skips p3: "Each name from the C standard library declared with external linkage is reserved to the implementation for use as a name with `extern "C"` linkage, both in namespace `std` and in the global namespace." – T.C. Jun 20 '18 at 07:43
  • @T.C. That seems very relevant. But I don't understand it really. Does this imply that `using namespace foo;` if `foo` contains, say, `abs(funny)` is illegal in the global namespace? – Walter Jun 20 '18 at 09:15
  • 1
    @T.C. Why is that relevant? I don't declare `abs` with C linkage. – xskxzr Jun 20 '18 at 09:39
  • @Walter: Why would that be the case? `using namespace Foo` only makes `Foo::abs` visible, it doesn't move `Foo::abs` to the global namespace. – MSalters Jun 20 '18 at 09:52
  • 1
    The name is reserved for use by the implementation in (among other things) the global namespace. The use to which the implementation puts it is not relevant. – T.C. Jun 21 '18 at 20:43
0

tl;dr - yes, you can

http://www.eel.is/c++draft/reserved.names#extern.names

Pulling in the rest of the context:

20.5.4.3.2: If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by this Clause, its behavior is undefined.

And then also

20.5.4.3.3.2 Each global function signature declared with external linkage in a header is reserved to the implementation to designate that function signature with external linkage.

20.5.4.3.3.4 Each function signature from the C standard library declared with external linkage is reserved to the implementation for use as a function signature with both extern "C" and extern "C++" linkage,182 or as a name of namespace scope in the global namespace.

These suggest you can, as it is only the signature that is reserved.

Bonus for namespace ::std

http://www.eel.is/c++draft/library#namespace.std

20.5.4.2.1.1 Unless otherwise specified, the behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std.

http://en.cppreference.com/w/cpp/language/extending_std has summarised the exceptions

Community
  • 1
  • 1
UKMonkey
  • 6,941
  • 3
  • 21
  • 30
  • There was no question of adding to `namespace std`, but to adding to the global namespace. – Walter Jun 19 '18 at 11:09
  • @Walter if the standard states explicitly that std can not be extended, but then doesn't say anything about the global namespace; and explicitly states that it is the function signatures that are reserved - then adding new ones in the global namespace isn't rejected by the standard... – UKMonkey Jun 19 '18 at 11:11
  • Do we need the part with `std` in this argumentation? – Walter Jun 19 '18 at 11:13
  • @Walter because the first parts suggest that you can overload any function in std too - which you can't, and I don't want this answer to suggest you can. – UKMonkey Jun 19 '18 at 11:14
  • This is a red herring. The question clearly related to the global namespace (only). – Walter Jun 19 '18 at 11:14
  • But the specification says "or as a name". Note it says "as a function signature" in the first half part. – xskxzr Jun 20 '18 at 07:14
  • @xskxzr "or" - used to link alternatives. That means one OR the other. If they're a function - they're reserved as a function. If they're a name, they're reserved as a name. – UKMonkey Jun 20 '18 at 09:09
  • But the subject is "each function signature". Well, I agree with you that this paragraph is weird, as StorryTeller pointed out in the [comment](https://stackoverflow.com/questions/50925440/can-reserved-function-names-be-overloaded?noredirect=1#comment88850354_50925440). – xskxzr Jun 20 '18 at 09:42
  • @xskxzr To be honest, not doing so is by far the safest thing; the c++ standard has been changing so fast in recent years the whole of the global namespace could end up reserved soon, but that wasn't your question ;) – UKMonkey Jun 20 '18 at 09:47