Why Is My Log in the Std Namespace

Why is my log in the std namespace?

C++ Standard 17.6.1.2 paragraph 4 (emphasis mine):

Except as noted in Clauses 18 through 30 and Annex D, the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in the C Standard library (1.2) or the C Unicode TR, as appropriate, as if by inclusion. In the C++ standard library, however, the declarations (except for names which are defined as macros in C) are within namespace scope (3.3.6) of the namespace std. It is unspecified whether these names are first declared within the global namespace scope and are then injected into namespace std by explicit using-declarations (7.3.3).

g++ does it the latter way so that some of the same header files can be reused for C and C++. So g++ is allowed to declare and define double log(double) in the global namespace.

Section 17.6.4.3.3 paragraphs 3 and 4:

Each name from the Standard C 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.

Each function signature from the Standard C 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.

And up at the top of Section 17.6.4.3 paragraph 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.

You, on the other hand, may not declare or define ::log in any way.

It's too bad the g++ toolchain doesn't give you any error messages, though.

What's the purpose of declaring namespace std {} ?

That's a forward declaration of a namespace. You are not allowed to 'use' a namespace before it has been declared, so the declaration is necessary if you don't have any includes that bring in any part of 'std' beforehand.

Is it actually useful or necessary... That's doubtful. If you are including anything that brings in any part of std, you don't need the forward declaration. And if you are not, you don't need that using namespace std. So it might be a bit of boilerplate code - someone who was taught to 'always write using namespace std', and writes it even if it doesn't make any sense.

Why am I able to use the names in the std namespace even though I'm using namespace std; ?

So why isn't there any naming conflict?

You're declaring a non-template max, and std::max is a set of overloaded function templates, so they're all overloaded. And the non-template version declared in the global namespace is selected in overload resolution here.

F1 is determined to be a better function than F2 if implicit
conversions for all arguments of F1 are not worse than the implicit
conversions for all arguments of F2, and

...


  1. or, if not that, F1 is a non-template function while F2 is a
    template specialization

...

issue with using namespace std;

You have a conflict with std::distance

using namespace std' is causing a strange behaviour

After fiddling around with the log() and suspecting the operator += () I finally solved this puzzle.

The actual error is caused by printf("%.5lf\n", ...).

I modified the sample code slightly to demonstrate:

#include<cmath>
#include<cstdio>
#include<iomanip>
#include<iostream>
using namespace std;
int main() {
int i, p, q, r, s;
while (scanf("%d %d %d %d", &p, &q, &r, &s) == 4) {
long double ans = 0;
if (p - q < q)
q = p - q;
if (r - s < s)
s = r - s;
for (i = 1; i <= q; i++)
ans += log(p - q + i) - log(i);
for (i = 1; i <= s; i++)
ans -= log(r - s + i) - log(i);
printf("printf: %.5lf", exp(ans));
cout << "\tcout: " << fixed << setprecision(5) << exp(ans) << endl;
}
return 0;
}

The output is now:

printf: 0.00000 cout: 0.12587
printf: 0.00000 cout: 505606.46055
printf: 0.00000 cout: 1.28223
printf: 0.00000 cout: 0.48996
printf: 0.00000 cout: 2.00000
printf: 0.00000 cout: 3.99960

I checked this on ideone.
The same output I get when I compile and run this with VS2013 on Windows 10 (64 bit).

I checked this also with gcc in cygwin on Windows 10 (64 bit) and got the following output:

$ g++ -std=c++11 -o test-longdouble test-longdouble.cc ; echo '10 5 14 9
> 93 45 84 59
> 145 95 143 92
> 995 487 996 488
> 2000 1000 1999 999
> 9998 4999 9996 4998
> ' | ./test-longdouble
printf: -0.00000 cout: 0.12587
printf: -4234002535919089587818586571373347278663379000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000 cout: 505606.46055
printf: -0.00000 cout: 1.28223
printf: -65094314467486612925155033958017324735054040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000 cout: 0.48996
printf: nan cout: 2.00000
printf: nan cout: 3.99960

$ g++ -std=c++14 -o test-longdouble test-longdouble.cc ; echo '10 5 14 9
93 45 84 59
145 95 143 92
995 487 996 488
2000 1000 1999 999
9998 4999 9996 4998
' | ./test-longdouble
printf: -0.00000 cout: 0.12587
printf: -4234002535919089587818586571373347278663379000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000 cout: 505606.46055
printf: -0.00000 cout: 1.28223
printf: -65094314467486612925155033958017324735054040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.00000 cout: 0.48996
printf: nan cout: 2.00000
printf: nan cout: 3.99960

$ g++ --version
g++ (GCC) 5.4.0

I didn't see it at the first glance but cout output is correct, only the printf output is different.

Considering that the printf formatter is chosen wrong you should not have any expectations about its effect.

Then I fixed the wrong formatting in printf():

#include<cmath>
#include<cstdio>
#include<iomanip>
#include<iostream>
using namespace std;
int main() {
int i, p, q, r, s;
while (scanf("%d %d %d %d", &p, &q, &r, &s) == 4) {
long double ans = 0;
if (p - q < q)
q = p - q;
if (r - s < s)
s = r - s;
for (i = 1; i <= q; i++)
ans += log(p - q + i) - log(i);
for (i = 1; i <= s; i++)
ans -= log(r - s + i) - log(i);
printf("printf: %.5Lf", exp(ans));
cout << "\tcout: " << fixed << setprecision(5) << exp(ans) << endl;
}
return 0;
}

Compiled and tested again with gcc in cygwin on Windows 10 (64 bit):

$ g++ -std=c++14 -o test-longdouble test-longdouble.cc ; echo '10 5 14 9
93 45 84 59
145 95 143 92
995 487 996 488
2000 1000 1999 999
9998 4999 9996 4998
' | ./test-longdouble
printf: 0.12587 cout: 0.12587
printf: 505606.46055 cout: 505606.46055
printf: 1.28223 cout: 1.28223
printf: 0.48996 cout: 0.48996
printf: 2.00000 cout: 2.00000
printf: 3.99960 cout: 3.99960

Thus, I can only repeat what I already stated in my comment: You really should use C++ stream output. printf() can cause weird behavior due to the slightest mistakes in formatters.

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.

What is using namespace::std in C++

using namespace::std is the same as using namespace std;

The :: symbol is the scope resolution operator. When used without a scope name before it , it refers to the global namespace. This means that std is a top level namespace, and is not enclosed in another.

The spaces before and after the :: are optional in this case because the lexer can deduce the tokens from the context.

For example, all of the following are valid:

namespace A { namespace notstd{} } // define my own namespaces A and A::notstd
using namespace::std; // the standard library std
using namespace A;
using namespace ::A;
using namespace::A;
using namespace A::notstd;

Update:

As noted in one of the comments, using namespace ::std; and using namespace std; may actually lead to different results if the statement comes inside another namespace which contains its own nested namespace std. See the following (highly unlikely) example:

#include <stdio.h>

namespace A {
namespace std {
int cout = 5;
}
using namespace std;
void f1() {
cout++;
}
}

int main()
{
A::f1();
printf("%d\n",A::std::cout); // prints 6

return 0;
}


Related Topics



Leave a reply



Submit