c++ namespace question

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

>-)
Posts: 527
Joined: Tue Apr 24, 2012 1:10 am UTC

c++ namespace question

Postby >-) » Tue Dec 22, 2015 3:13 am UTC

After I #include <stdlib.h>, I can use stuff like std::array.
And after I #include <math.h> I can call sqrt.

But why is it just sqrt and not math::sqrt?

I feel like this should be simple, but I haven't been able to find anything on it

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6299
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: c++ namespace question

Postby Thesh » Tue Dec 22, 2015 3:25 am UTC

All the <xxxx.h> headers declare variables in the global namespace. All the standard <xxxx> headers declare variables in the std namespace. If <stdlib.h> happens to include <array> then including it may declare std:array but it is not guaranteed or even expected. If you are using C++ you should avoid the <xxxx.h> headers.

There is no standard math namespace defined.
Summum ius, summa iniuria.

>-)
Posts: 527
Joined: Tue Apr 24, 2012 1:10 am UTC

Re: c++ namespace question

Postby >-) » Tue Dec 22, 2015 3:30 am UTC

Ah, thanks. So I guess I should be using #include <cmath> and std::sqrt instead.

User avatar
phlip
Restorer of Worlds
Posts: 7556
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: c++ namespace question

Postby phlip » Wed Dec 23, 2015 9:50 am UTC

>-) wrote:Ah, thanks. So I guess I should be using #include <cmath> and std::sqrt instead.

Yep. In general, for functions in the C standard library that you want to call from C++, the preferred method is to include <cwhatever> and call std::somefunction(). But you can also import <whatever.h> and just call somefunction() in the global namespace. The second option is there for back-compatibility with C, and should generally be avoided for C++ code.

So import <math.h> and you'll get sqrt, import <cmath> and you'll get std::sqrt. Import <string.h> and you'll get strlen, import <cstring> and you'll get std::strlen. And so on.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

korona
Posts: 495
Joined: Sun Jul 04, 2010 8:40 pm UTC

Re: c++ namespace question

Postby korona » Wed Dec 23, 2015 3:25 pm UTC

The problem is that most (all?) C++ standard libraries implement the <csomething> headers as:

Code: Select all

#include <math.h>

namespace std {
    using sqrt;
    using cos;
    [...]
}

So that the global namespace is still as polluted as it is for C.

User avatar
phlip
Restorer of Worlds
Posts: 7556
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: c++ namespace question

Postby phlip » Thu Dec 24, 2015 12:03 am UTC

That's implementation dependent. The standard guarantees that importing <cmath> declares std::sqrt and explicitly leaves undefined whether it declares ::sqrt... and it guarantees that importing <math.h> declares ::sqrt and explicitly leaves undefined whether it declares std::sqrt.

I've seen implementations that do it the other way... <cmath> declares std::sqrt, then <math.h> #includes <cmath> and then has "using std::sqrt".

Cygwin on my computer does it your way around (which I think is kinda dumb, but it is what it is) but the old Borland compiler I use at work sometimes does it this way around. And I'm pretty sure I've seen GCC-related implementations that do it this way, though I can't remember details (possibly the one with devkitPro? I think that might've been what I was using when I learned about the <csomething>/<something.h> dichotomy).

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

korona
Posts: 495
Joined: Sun Jul 04, 2010 8:40 pm UTC

Re: c++ namespace question

Postby korona » Thu Dec 24, 2015 12:53 am UTC

Yeah I know that it is implementation dependent but I have never seen it the other way around. The problem is that the are no namespaces and using statements in plain C and you want a <math.h> that can be included from C source files. The only real other way would be to provide two implementations (or a real implementation plus a wrapper) for each function or to rely on compiler specific stuff like __attribute__ (( weakref("sqrt") )).

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6299
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: c++ namespace question

Postby Thesh » Thu Dec 24, 2015 1:44 am UTC

What's wrong with doing this?

Code: Select all

namespace std {
    extern "C" {
        #include <math.h>
    }
}
Summum ius, summa iniuria.

User avatar
phlip
Restorer of Worlds
Posts: 7556
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: c++ namespace question

Postby phlip » Thu Dec 24, 2015 2:25 am UTC

Is it guaranteed by spec that two extern "C" functions with the same name in different namespaces will link together? I'm too lazy to go check.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

User avatar
Thesh
Made to Fuck Dinosaurs
Posts: 6299
Joined: Tue Jan 12, 2010 1:55 am UTC
Location: Colorado

Re: c++ namespace question

Postby Thesh » Thu Dec 24, 2015 2:31 am UTC

Well, if you use extern C, then the names won't use C++ name mangling. So it's going to be a problem if you are using a C library with functions that are named the same as in the C standard library, and a C library whose names collide with the C standard library are not going to work with C programs either.
Summum ius, summa iniuria.

User avatar
phlip
Restorer of Worlds
Posts: 7556
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: c++ namespace question

Postby phlip » Thu Dec 24, 2015 4:24 am UTC

To answer my own question, the spec does say "Two declarations for a function with C language linkage with the same function name (ignoring the namespace names that qualify it) that appear in different namespace scopes refer to the same function."

So you could have <math.h> have extern "C" double sqrt(double);, and <cmath> have namespace std {extern "C" double sqrt(double);}, and both of these would happily link to the same function from libm.a and you'd still be fine within the spec. I was thinking there was a reasonable chance this would just be undefined behaviour that just happens to work.

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]

korona
Posts: 495
Joined: Sun Jul 04, 2010 8:40 pm UTC

Re: c++ namespace question

Postby korona » Thu Dec 24, 2015 9:42 am UTC

That breaks down if math.h has also included in the same compilation unit.

Code: Select all

#include <math.h>
#include <cmath>
// now i have ::sqrt but not std::sqrt


Code: Select all

#include <cmath>
#include <math.h>
// now i have std::sqrt but not ::sqrt


A possible implementation would be

Code: Select all

#include <all_the_macros_from_math.h>
extern "C" {
    #include <all_the_functions_from_math.h>
}

where all_the_macros_from_math.h has an include guard but all_the_functions_from_math.h does not have a guard. However this assumes a certain implementation of the C standard library and makes the C++ standard library less portable.

User avatar
phlip
Restorer of Worlds
Posts: 7556
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia
Contact:

Re: c++ namespace question

Postby phlip » Thu Dec 24, 2015 1:41 pm UTC

korona wrote:However this assumes a certain implementation of the C standard library and makes the C++ standard library less portable.

That's a point I hadn't considered... if your C stdlib and your C++ stdlib are separate projects, and you're reusing the <math.h> from the one in the other (which it would make sense to do), then you'd want to have <cmath> include <math.h> instead of the other way around. The toolchains I've seen that do it the other way around were self-contained entities, as opposed to linux's habit of having a couple dozen separate projects all working together...

Code: Select all

enum ಠ_ಠ {°□°╰=1, °Д°╰, ಠ益ಠ╰};
void ┻━┻︵​╰(ಠ_ಠ ⚠) {exit((int)⚠);}
[he/him/his]


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 7 guests