As far as I understand it C-entities used by C++ like those in <math.h> can be included in a safe way inside an std namespace by including their corresponding <c...> variant (except macros, obviously). cppreference seems to confirm this.
However, including <cmath> appears to pull in the log function outside the std namespace:
#include <cmath>
namespace log {}
int main() {}
Compiled with g++ -Wall -Wextra -pedantic -std=c++17 a.cpp yields:
a.cpp:3:11: error: ‘namespace log { }’ redeclared as different kind of entity
3 | namespace log {}
| ^~~
In file included from /usr/include/features.h:446,
from /usr/include/x86_64-linux-gnu/c++/9/bits/os_defines.h:39,
from /usr/include/x86_64-linux-gnu/c++/9/bits/c++config.h:524,
from /usr/include/c++/9/cmath:41,
from a.cpp:1:
/usr/include/x86_64-linux-gnu/bits/mathcalls.h:104:1: note: previous declaration ‘double log(double)’
104 | __MATHCALL_VEC (log,, (_Mdouble_ __x));
| ^~~~~~~~~~~~~~
Is my standard library broken? Can I do something to avoid this?
I originally stumbled over this using <random>, which means that more headers might be affected by apparently random C-entities being spewed all across the top level namespace.
Why does <cmath> expose entities outside the std namespace?
Because of history.
<cmath> header is a header inherited from the C standard library (where it is named <math.h>). In the C language, there is only the global namespace1 where all names are declared.
Since many C++ implementations are also C implementations, they often implement the inherited C standard header by including it as-is2 which means that it declares global names.
While there may be techniques to avoid (except in case of standard macros) declaring global names, it is unlikely that implementations that have been doing it since before standardisation would change the behaviour because that would break backward compatibility.
Is my standard library broken?
No. C++ standard allows this; All C standard library names are reserved for this (or any) use by the language implementation. You may not define them yourself.
Can I do something to avoid this?
You generally cannot prevent a standard library doing this.
You can technically avoid most of it by choosing to use a freestanding language implementation. But you'll lose nearly the entire standard library if you choose that.
You can minimise chances of name clashes by avoiding declaration of any global names yourself, except for a single namespace with sufficiently unique name. Something like:
namespace usr_bitmask::log {
}
1 Note that the concept of "name space" in the C language is something else.
2 And additionally, re-declares the names in the std namespace when using the <c... named header, as well as adds C++ specific overloads in some cases.
Maybe someone with more C/C++ Standard knowledge will prove me wrong, but for a C++ compiler to also being able to process C-Code, functions from the C-Library need to be outside of namespaces, in fact you should just find the C-Library definitions enclosed in a extern "C", so you can use the old C functions inside you C++ code transparently
Related
I am using only header files specific to C++ (e.g. <cstdlib>), however I still get globally-declared functions, and not just functions in the std namespace. Is there a way, perhaps a compiler switch, to prevent that?
For example, the following code:
#include <cstdlib>
float random() { return 0.0f; }
int main() { return 0; }
Fails to compile under linux, with the following error:
> g++ -c main.cpp main.o
main.cpp: In function ‘float random()’:
main.cpp:2:14: error: new declaration ‘float random()’
/usr/include/stdlib.h:327:17: error: ambiguates old declaration ‘long int random()’
or
> clang++ main.cpp -o main.o
main.cpp:2:7: error: functions that differ only in their return type cannot be overloaded
float random() { return 0.0f; }
/usr/include/stdlib.h:327:17: note: previous declaration is here
extern long int random (void) __THROW;
which is caused that stdlib.h "pollutes" the global namespace with its own random function.
Note, that I am not facing these problems when compiling on Windows, using Visual Studio.
<cstdlib> will always populate std namespace, and sometimes define global symbols, while <stdlib.h> will always define global symbols, and sometimes populate std namespace. This varies from implementation to implementation.
The standard writes:
Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).
Which means, that the compiler is allowed to put those symbols into global scope and std namespace at the same time.
Therefore, we see no advantages to prefer one header file over the other. Because they are both very likely to pollute the global scope.
However, it is still necessary to use std namespace when #include <cstdlib>, and do not use std when #include <stdlib.h>, to make sure your code can compile for all compiler implementations.
Advice: Do not use names in standard libraries. First, they are not guaranteed to work. (Note: Few compiler implementations actually keep the global scope clean when you #include <csomething>, so never depend on this.) Second, it will confuse code readers and maintainers, because almost everyone will assume standard names are actually standard, no matter where they come from.
You can declare your functions in their own namespaces to prevent declaration collision.
namespace MyFunc
{
float random() { return 0.0f; }
};
In general you should try to avoid redeclaring in the first place.
You can do this by either using namespaces or by splitting up your source into files which can include cstdlib and others which can use a static version of your (name clashing) function.
If this is not an options then go on reading. But be aware that the following might be very platform specific.
By just having a look at my cstdlib and stdlib.h here at my place I noticed that there is a switch by which cstdlib decides if it includes stdlib.h or just declares abort, atext and exit in the std namespace.
Obviously you pull in the stdlib.h branch. Looking further into this file I noticed the macro __BEGIN_NAMESPACE_STD and later on __END_NAMESPACE_STD. Maybe you could use this, but it is (as the name suggests) some implementation internal macro and should not be set directly by you. However, it should be there for some reason so you might have luck with searching for it.
After some more search it turned out that random is one of several functions (and declarations) which are not wrapped into __BEGIN_NAMESPACE_STD. Therefore, this is not a solution to the problem. (I found another macro _GLIBCPP_USE_NAMESPACES which seems to be used internally as well to #define __BEGIN_NAMESPACE_STD namespace std {).
So to sum it up: This is no viable path and you should use one of the described workarounds.
The standard explicitly permits <c???> headers to bring names of C standard functions to the global namespace.
usually I would prefer to keep your function names different from what is defined as a standard .
For ex here one could use function name as myRandom instead of random so that I can inform the people , who would be maintaining my code later on , that the function being used is NOT the one defined as a standard.
Time and again I run into problems from namespace pollution due to indirect inclusion of C-header files from C++ standard headers. For example, on my linux system gcc's (version 5.1.1) <thread> includes usr/include/bits/sched.h, which declares
extern "C" {
extern int clone(int (*__fn) (void *__arg), void *__child_stack, int __flags, void *__arg, ...) throw();
}
In the following minimal example
#include <thread> // indirect inclusion of <sched.h>
namespace {
struct foo
{ virtual foo*clone() const=0; };
foo*clone(std::unique_ptr<foo> const&); // function intended
struct bar : foo
{
std::unique_ptr<foo> daughter;
bar(foo*d) : daughter(d) {}
foo*clone() const
{ return new bar(::clone(daughter)); } // to be called here
};
}
the compiler complains about the call to ::clone() not matching the definition from bits/sched.h (ignoring the definition just before). (Note that simply calling clone instead of ::clone clashes with the member.)
So, the questions are:
Is gcc correct to discard my version of clone() when trying to resolve the function call ::clone(daughter)?
Is the pollution of the global namespace in this way standard compliant?
In the above example, can I resolve the problem without renaming my clone() functions (or the anonymous namespace) but still including <thread>?
Is gcc correct to discard my version of clone() when trying to resolve the function call ::clone(daughter)?
Yes, I think so.
Is the pollution of the global namespace in this way standard compliant?
It's arguable. For a pure C++ implementation, no, but there aren't many of them. In practice most are "C++ on POSIX" or "C++ on Windows" implementations and declare lots of names that are not in the C++ standard.
The namespace pollution problem is well known (11196, 51749 and others), with no simple solution.
The problem is that most C++ standard library implementations don't control the C library and just include the platform's native C headers, which pull in other names.
In the above example, can I resolve the problem without renaming my clone() functions (or the anonymous namespace) but still including ?
In your specific case you can solve the name lookup problem by putting your clone overload in the global namespace so lookup finds it at the same time as the function in <sched.h> and by making it static to give it internal linkage again.
yes, because ::clone looks for clone first in the global (outermost) namespace, and then in the anonymous namespace.
Nothing prevents you (or library providers) to pollute any namespace (global included) but 'std' which is reserved for the standard.
Naming the anonymous namespace could be a way out.
If the question #2 is "Does the standard allow the pollution of global namespace by including a standard header, i.e. making available more symbols than the standard require?". Then I guess the answer is yes, otherwise the constraint imposed on standard library vendors could be too stringent.
Implementation is allowed to put definitions into the global namespace in some cases.
First, a C++ library header is allowed to include other C++ headers:
N3337 17.6.5.2 Headers [res.on.headers] P1:
A C++ header may include other C++ headers. A C++ header shall provide the declarations and definitions
that appear in its synopsis. A C++ header shown in its synopsis as including other C++ headers shall provide
the declarations and definitions that appear in the synopses of those other headers.
The included C++ header can be a wrapper for a C library. Names of these C++ headers start with c, like <cstdlib>.
These headers are allowed to put corresponding C-library definitions in the global namespace first, and then inject them into std namespace.
17.6.1.2 Headers [headers] P4:
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).
Thus, the functions defined in the C standard library can end up in the global namespace.
The clone function, however, in not part of C standard library (it is part of POSIX standard) and thus not formally allowed to appear in the global namespace by the C++ standard.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it a good idea to wrap an #include in a namespace block?
I've got a project with a class log in the global namespace (::log).
So, naturally, after #include <cmath>, the compiler gives an error message each time I try to instantiate an object of my log class, because <cmath> pollutes the global namespace with lots of three-letter methods, one of them being the logarithm function log().
So there are three possible solutions, each having their unique ugly side-effects.
Move the log class to it's own namespace and always access it with it's fully qualified name. I really want to avoid this because the logger should be as convenient as possible to use.
Write a mathwrapper.cpp file which is the only file in the project that includes <cmath>, and makes all the required <cmath> functions available through wrappers in a namespace math. I don't want to use this approach because I have to write a wrapper for every single required math function, and it would add additional call penalty (cancelled out partially by the -flto compiler flag)
The solution I'm currently considering:
Replace
#include <cmath>
by
namespace math {
#include "math.h"
}
and then calculating the logarithm function via math::log().
I have tried it out and it does, indeed, compile, link and run as expected. It does, however, have multiple downsides:
It's (obviously) impossible to use <cmath>, because the <cmath> code accesses the functions by their fully qualified names, and it's deprecated to use in C++.
I've got a really, really bad feeling about it, like I'm gonna get attacked and eaten alive by raptors.
So my question is:
Is there any recommendation/convention/etc that forbid putting include directives in namespaces?
Could anything go wrong with
diferent C standard library implementations (I use glibc),
different compilers (I use g++ 4.7, -std=c++11),
linking?
Have you ever tried doing this?
Are there any alternate ways to banish the math functions from the global namespace?
I've found several similar questions on stackoverflow, but most were about including other C++ headers, which obviously is a bad idea, and those that weren't made contradictory statements about linking behaviour for C libraries. Also, would it be beneficial to additionally put the #include <math.h> inside extern "C" {}?
edit
So I decided to do what probably everyone else is doing, and put all of my code in a project namespace, and to access the logger with it's fully qualified name when including <cmath>.
No, the solution that you are considering is not allowed. In practice what it means is that you are changing the meaning of the header file. You are changing all of its declarations to declare differently named functions.
These altered declarations won't match the actual names of the standard library functions so, at link time, none of the standard library functions will resolve calls to the functions declared by the altered declarations unless they happen to have been declared extern "C" which is allowed - but not recommended - for names which come from the C standard library.
ISO/IEC 14882:2011 17.6.2.2/3 [using.headers] applies to the C standard library headers as they are part of the C++ standard library:
A translation unit shall include a header only outside of any external declaration or definition[*], and shall include the header lexically before the first reference in that translation unit to any of the entities declared in that header.
[*] which would include a namespace definition.
Why not putting a log class in it's own namespace and using typedef namespace::log logger; to avoid name clashes in a more convenient way?
Change your class's name. Not that big of a deal. ;-)
Seriously though, it's not a great idea to put names in the global namespace that collide with names from any standard header. C++03 didn't explicitly permit <cmath> to define ::log. But implementations were chronically non-conforming about that due to the practicalities of defining <cmath> on top of an existing <math.h> (and perhaps also an existing static-link library for some headers, including math). So C++11 ratifies existing practice, and allows <cmath> to dump everything into the global namespace. C++11 also reserves all those names for use with extern "C" linkage, and all function signatures for use with C++ linkage, even if you don't include the header. But more on that later.
Because in C++ any standard header is allowed to define the names from any other standard header (i.e, they're allowed to include each other), this means that any standard header at all can define ::log. So don't use it.
The answer to your question about different implementations is that even if your scheme works to begin with (which isn't guaranteed), in some other implementation there might be a header that you use (or want to use in future in the same TU as your log class), that includes <cmath>, and that you didn't give the namespace math treatment to. Off the top of my head, <random> seems to me a candidate. It provides a whole bunch of continuous random number distributions that plausibly could be implemented inline with math functions.
I suggest Log, but then I like capitalized class names. Partly because they're always distinct from standard types and functions.
Another possibility is to define your class as before and use struct log in place of log. This doesn't clash with the function, for reasons that only become clear if you spend way too much time with the C and C++ standards (you only use log as a class name, not as a function and not as a name with "C" linkage, so you don't infringe on the reserved name. Despite all appearances to the contrary, class names in C++ still inhabit a parallel universe from other names, rather like struct tags do in C).
Unfortunately struct log isn't a simple-type-identifier, so for example you can't create a temporary with struct log(VERY_VERBOSE, TO_FILE). To define a simple-type-identifier:
typedef struct log Log;
Log(VERY_VERBOSE, TO_FILE); // unused temporary object
An example of what I say in a comment below, based on a stated example usage. I think this is valid, but I'm not certain:
#include <iostream>
#include <cmath>
using std::log; // to enforce roughly what the compiler does anyway
enum Foo {
foo, bar
};
std::ostream &log(Foo f) { return std::cout; }
int main() {
log(foo) << log(10) << "\n";
}
It is ugly hack too, but I believe will not cause any linker problems. Just redefine log name from <math.h>
#define log math_log
#include <math.h>
#undef log
It could cause problems with inline functions from math using this log, but maybe you'd be lucky...
Math log() is still accessible but it's not easy. Within functions where you want to use it, just repeat its real declaration:
int somefunc() {
double log(double); // not sure if correct
return log(1.1);
}
So this is something that I've always wondered but was never quite sure about. So it is strictly a matter of curiosity, not a real problem.
As far as I understand, whenyou do something like #include <cstdlib> everything (except macros of course) are declared in the std:: namespace. Every implementation that I've ever seen does this by doing something like the following:
#include <stdlib.h>
namespace std {
using ::abort;
// etc....
}
Which of course has the effect of things being in both the global namespace and std. Is this behavior guaranteed? Or is it possible that an implementation could put these things in std but not in the global namespace? The only way I can think of to do that would be to have your libstdc++ implement every c function itself placing them in std directly instead of just including the existing libc headers (because there is no mechanism to remove something from a namespace). Which is of course a lot of effort with little to no benefit.
The essence of my question is, is the following program strictly conforming and guaranteed to work?
#include <cstdio>
int main() {
::printf("hello world\n");
}
EDIT: The closest I've found is this (17.4.1.2p4):
Except as noted in clauses 18 through
27, the contents of each header cname
shall be the same as that of the
corresponding header name.h, as
specified in ISO/IEC 9899:1990
Programming Languages C (Clause 7), or
ISO/IEC:1990 Programming Languages—C
AMENDMENT 1: C Integrity, (Clause 7),
as appropriate, as if by inclusion. In
the C + + Standard Library, however,
the declarations and definitions
(except for names which are defined as
macros in C) are within namespace
scope (3.3.5) of the namespace std.
which to be honest I could interpret either way. "the contents of each header cname shall be the same as that of the corresponding header name.h, as specified in ISO/IEC 9899:1990 Programming Languages C" tells me that they may be required in the global namespace, but "In the C + + Standard Library, however, the declarations and definitions (except for names
which are defined as macros in C) are within namespace scope (3.3.5) of the namespace std." says they are in std (but doesn't specify any other scoped they are in).
Here's a nice synopsis of the situation (with some reality vs. what the standard says) from Stephan T. Lavavej of the MSVC team (http://blogs.msdn.com/vcblog/archive/2008/08/28/the-mallocator.aspx#8904359):
> also, <cstddef>, <cstdlib>, and std::size_t etc should be used!
I used to be very careful about that. C++98 had a splendid dream wherein <cfoo> would declare everything within namespace std, and <foo.h> would include <cfoo> and then drag everything into the global namespace with using-declarations. (This is D.5 [depr.c.headers].)
This was ignored by lots of implementers (some of which had very little control over the C Standard Library headers). So, C++0x has been changed to match reality. As of the N2723 Working Paper, http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2723.pdf , now <cfoo> is guaranteed to declare everything within namespace std, and may or may not declare things within the global namespace. <foo.h> is the opposite: it is guaranteed to declare everything within the global namespace, and may or may not declare things within namespace std.
In reality and in C++0x, including <cfoo> is no safeguard against everything getting declared in the global namespace anyways. That's why I'm ceasing to bother with <cfoo>.
This was Library Issue 456, http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#456 .
(C++0x still deprecates the <foo.h> headers from the C Standard Library, which is hilarious.)
I've never been fond of the <cfoo> headers myself, and found that I've always use <foo.h>. Now I feel like I can stop being anxious about my lack of C++ 'purity' in that regard.
At the present time, no. In fact, even though the code will work with every compiler I now of, it's really not supposed to work at all -- #includeing one of the c* headers is only supposed to give you access to the names inside of namespace std.
Since implementation of this was such a pain (getting it right essentially required duplicating the entire C library as a C++ library in the right namespace), in C++ 0x they've changed the requirements a bit -- your code is now allowed to work, though (at least if memory serves) it's still not required to work.
I cannot speak for the standards, as I have not read them, but one could envision a C++ environment that is not built on top of a C environment, or where the C environment is a compatibility layer on top of underlying C++ APIs. In such a case, these guarantees may not be made. I would be surprised if such an implementation would be prohibited from being a compliant implementation.
The C++ Programming Language : Special Edition states on page 431 that...
For every header < X.h > defining part of the C standard library in the global namespace and also in namespace std, there is a header < cX > defining the same names in the std namespace only.
However, when I use C headers in the < cX > style, I don't need to qualify the namespace. For example...
#include <cmath>
void f() {
double var = sqrt( 17 );
}
This would compile fine. Even though the book says that using the < cX > header defines names in the std namespace only, you are allowed to use those names without qualifying the namespace. What am I missing here?
P.S. Using the GNU.GCC compiler
Stephan T. Lavavej, a member of the MSVC team, addresses the reality of this situation (and some of the refinements to the standard) in this comment on one of his blog postings (http://blogs.msdn.com/vcblog/archive/2008/08/28/the-mallocator.aspx#8904359):
> also, <cstddef>, <cstdlib>, and std::size_t etc should be used!
I used to be very careful about that. C++98 had a splendid dream wherein <cfoo> would declare everything within namespace std, and <foo.h> would include <cfoo> and then drag everything into the global namespace with using-declarations. (This is D.5 [depr.c.headers].)
This was ignored by lots of implementers (some of which had very little control over the C Standard Library headers). So, C++0x has been changed to match reality. As of the N2723 Working Paper, http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2723.pdf , now <cfoo> is guaranteed to declare everything within namespace std, and may or may not declare things within the global namespace. <foo.h> is the opposite: it is guaranteed to declare everything within the global namespace, and may or may not declare things within namespace std.
In reality and in C++0x, including <cfoo> is no safeguard against everything getting declared in the global namespace anyways. That's why I'm ceasing to bother with <cfoo>.
This was Library Issue 456, http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#456 .
(C++0x still deprecates the <foo.h> headers from the C Standard Library, which is hilarious.)
I'm in 100% agreement with Lavavej, except I never tried to be very careful about using the <cfoo> style headers even when I first started using C++ - the standard C ones were just too ingrained - and there was never any real world problem using them (and apparently there was never any real world benefit to using the <cfoo> style headers).
The rule for the C libraries differs from C++ libraries for namespaces
gcc interprets the standard in Gcc docs as
The standard specifies that if one includes the C-style header (<math.h> in this case), the symbols will be available in the global namespace and perhaps in namespace std:: (but this is no longer a firm requirement.) One the other hand, including the C++-style header (<cmath>) guarantees that the entities will be found in namespace std and perhaps in the global namespace.
In the draft C0X++ spec it says in section 17.6.2.3 Headers
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
It's hard to fix this without implementing the C library twice. See DR 456, which basically proposes giving up on the problem.
Why do you say "This would compile fine" when it violates the Standard? Who allows you to use those names without qualifying the namespace? Have you tested this on a particular implementation and found that it works?
I strongly advise against using some particular non-standard feature because it happens to work on your compiler of choice. Such things break easily, perhaps with a later version of the same compiler.
You are probably missing using a standards-conformant compiler (or the one you use is configured to be compatible with pre-standard code).