Single-Level Control Break

Pages: 12
So my counter argument is, don't mix namespaces.

Which is an excellent counter argument against using the using namespace clause in the first place. IMO you should be specifying the proper namespace at all times. The problem with your argument is that the error messages for this kind of problem are generally cryptic which makes finding the problem harder. So in that snippet you should be properly scoping both the std::namespace and the ::global namespace.

By the way I left off the printout to show that even with some of the smallest programs you can have unexpected name collisions.

My program was also just one of many and involves a function. Don't forget that name collisions can happen between variables as well. The standard uses quite a few common names that are subject to these unexpected collisions.

You have a single short source file written by you. You knew (how?) that this set of headers has identifier "toupper" in both global and std namespaces and that you want the global version.

That is not a huge challenge. It falls in what Ganado formulated:
it's OK to put in implementation (.cpp) files as long as you know what you're doing.



You have larger project. More code. Maintained by someone less knowledgeable. (Yes, contrary to common belief there are developers, who don't know everything perfectly. I don't know where they come from.)

Your code uses a global identifier. There has never been a name conflict, so you have "saved typing" the :: to be explicit. Now, years later, the C++ Standard Committee makes the serious "mistake". They add a new identifier to one of the std headers that you use. Identical to yours.

The maintainer spends additional time recompiling the code due to issue that should not have been there in the first place. Who is to blame, the committee or you? Both?
Well keskiverto, you just made two very good points.

I think my problem stems from the fact that I have no coder friends and therefor am a lone wolf coder. Nobody less knowledgeable than me touches my code, mostly because nobody at all, but me, touches my code.

People in group projects have a very different situation. I can see here where using namespace std; might frustrate some.

And as for your second point, well in never occurred to me, but that would be an interesting dilemma.
Why does one not have to put std:: before functions (such as printf) that were inherited from C?
Or, for that matter, the functions in <cmath>, some of which weren't inherited from C.

I find this inconsistent.

And if I decide to create my own function sech (hyperbolic sec), but years later the C++ Standards Committee decides to put such a function in <cmath>, where it doesn't need the std:: qualifier. What then?
Last edited on
Why does one not have to put std:: before functions (such as printf) that were inherited from C?

Probably because the people that implemented your compiler decided to place the information in both the global and std namespaces. Remember if you include the standard C++ version of the C standard headers the compiler is required to put those definitions in the std namespace. If you include the C standard headers then the definitions are required to be in the global namespace. It is implementation defined whether or not the definitions are placed in the other namespace.

And if I decide to create my own function sech (hyperbolic sec), but years later the C++ Standards Committee decides to put such a function in <cmath>, where it doesn't need the std:: qualifier. What then?

Have you looked at how the compiler implementations already handle this type of situation? Remember C++ already has several overloads of some of the C standard functions. I would expect the compiler to treat this case just like it does the current overloads. Of course I would also expect the C compiler to know nothing of your function or the current overloads of those C standard functions.

Last edited on
But it's not just my compiler - examples here, there and everywhere (including the reference on this website) seem to suggest that all the C standard library (headers starting <c...> ) seems to be put in the global namespace, not needing qualifying with std::, whereas everything in headers added by C++ does. Is that the case and, if so, where is it written down?

Is it implementation-defined what happens if I write my own function printf, but also include the header <cstdio>?
Last edited on
lastchance wrote:
Why does one not have to put std:: before functions (such as printf) that were inherited from C?


There is a std::printf and it is slightly different to printf IIRC, the C++ version is statically typesafe. I am sure that is in the C++ standard somewhere. Edit: I found it C++17 standard section 20.2 paragraphs 1 and 2. http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/n4659.pdf

standard wrote:

20.2 The C standard library
[library.c]
1
The C ++ standard library also makes available the facilities of the C standard library, suitably adjusted to
ensure static type safety.
2
The descriptions of many library functions rely on the C standard library for the semantics of those functions.
In some cases, the signatures specified in this International Standard may be different from the signatures
in the C standard library, and additional overloads may be declared in this International Standard, but
the behavior and the preconditions (including any preconditions implied by the use of an ISO C
restrict
qualifier) are the same unless otherwise stated.




To the OP, no one seems to have mentioned that is actually a good idea to put ones own code into it's own namespace/s. One can use a namespace alias to shorten the name in a particular file. You can Google how to do that if you wish.

Last edited on
Is it implementation-defined what happens if I write my own function printf, but also include the header <cstdio>?

I'm inclined to say the behavior is undefined.
15.5.4.3/2 [reserved.names] has:
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.
http://eel.is/c++draft/constraints#reserved.names-2

Later in the clause,
15.5.4.3.3/4 [extern.names] has:
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.
http://eel.is/c++draft/constraints#extern.names-4

Note: Don't pay too much attention to the clause number in the quotes above. In n4659 the clause number is 20, but the wording is the same.
Last edited on
Thank-you @TheIdeasMan and @mbozzi for looking those up.
keskiverto wrote:
(Yes, contrary to common belief there are developers, who don't know everything perfectly. I don't know where they come from.)

This made me laugh, thank you.

Manga, I think the others already said the gist of it, so I won't repeat that, but the reason I said don't put it in header files is because a header file is meant as the interface to the code, to be included into multiple, unrelated files. (It's also why header guard #macros should be unique.) If you think you know what you're doing, and your files aren't meant to see the light of day from others, then do whatever you want :) But even on larger solo projects, I know I can easily forget how something works after not looking at it for a month.

PS: Languages like C# and Java don't have this particular problem because using statements can only be file-scope. A using statement in a class file will never affect another part of the code that uses that class. Just thought that was an interesting point.
Eventually we'll get modules, which will solve this problem for good.
@Ganado

So when we put using namespace into a header, then other parts of code get affected? I want to play around with that idea, so I can better understand it.
So when we put using namespace into a header, then other parts of code get affected?

Yes when you put a "using statement" in the global scope of a header every file that #includes that header now has that "using statement" as well. Remember that the contents of a header file are copied into every file that #includes them.

We did already conclude that this code is happy without:

foo.cpp
1
2
3
4
5
6
7
8
9
#include <cctype>
#include <vector>
#include <algorithm>

int main()
{
    std::vector<char> my_vec{'a','b','d'};
    std::transform(my_vec.begin(), my_vec.end(), my_vec.begin(), toupper);
}


Lets say that there is
bar.h
1
2
3
4
5
6
7
8
#ifndef BAR_H
#define BAR_H
#include <vector>
using namespace std;
struct Bar  {
  vector<int> fubar;
};
#endif BAR_H 


Innocent include:
foo.cpp
1
2
3
4
5
6
7
8
9
10
11
12
#include <cctype>
#include <vector>
#include <algorithm>
#include "bar.h"

int main()
{
    std::vector<char> my_vec{'a','b','d'};
    std::transform(my_vec.begin(), my_vec.end(), my_vec.begin(), toupper); // error

    Bar snafu;
}


If we had written less in the header:
bar.h
1
2
3
4
5
6
7
8
#ifndef BAR_H
#define BAR_H
#include <vector>

struct Bar  {
  std::vector<int> fubar;
};
#endif BAR_H 

the foo.cpp would not have encountered a problem.


Lets go one step further. We have "perfect" code:
1
2
3
4
#include "gaz.h"

int main() {
}

And we add an include:
1
2
3
4
5
#include "bar.h"
#include "gaz.h" // errors

int main() {
}

Sorry, forgot that gaz.h cannot cope with std names in global namespace. "Lazy" author.

Indeed, this would have been ok:
1
2
#include "gaz.h" // ok, no namespace pollution
#include "bar.h" 


These are still too trivial. The bar.h is included in about two translation units. A useful header would be used by many, many more. Any change in the header would affect them all.
Thanks keskiverto.

I can't believe I had never realized any of this before now...
Topic archived. No new replies allowed.
Pages: 12