visibility problems with namespaces - c++

I have two source files, one named main.cpp (where the namespace M is defined) and the file engines.h (where several names are defined).
main.cpp includes engines.h.
engines.h need to use the stuff inside M, and M needs to use the stuff inside engines.h.
I get an error doing using namespace M; in engines.h.

Don't use using namespace inside header files. This will get all the symbols from the namespace inside each translation unit that includes that header file, so you'll have a symbol mess (name conflict, which is probably what you're facing in your situation). Use full qualification inside the header files, or at least use the using namespace statement locally (inside a function or method where you what to improve readability).
For your situation, what is the error you get? What is the content of the headers?

You cannot do using namespace M before the namespace was defined. If there is a cyclic dependency, you need to solve it by using one or more techniques
Forward declare if your uses don't need to know the members or size of classes, but just handle with pointers or references to them:
namespace M { class MyCow; }
Define stuff in engines.cc
// engines.h
void f();
// engines.cpp
#include "main.h"
void f() { MyCow muuh; }
Use of the pimpl idiom reduces dependencies even more, as it keeps headers free of headers that are only used by implementations..
Split the part in .h files for the interface and .cpp files for the implementation to handle such dependencies. That way, headers are less dependent on other headers, and implementation files can include the headers.

Related

How to use "using" keyword in C++

I am little confused as to which one is the better way to use using C++ keyword for namespaces. Suppose that the following code is in a header file backtrace.h
#include <memory>
using my_namespace1::component1;
using my_namespace2::component2;
namespace my_application {
namespace platform_logs {
class backtrace_log {
//code that creates instances of my_namespace1::component1 and my_namespace2::component2
};
}
}
OR
#include <memory>
namespace my_application {
namespace platform_logs {
using my_namespace1::component1;
using my_namespace2::component2;
class backtrace_log {
//code that creates instances of my_namespace1::component1 and my_namespace2::component2
};
}
}
which one is better and why ?
You should always pull in symbols from other namespaces in as narrow a scope as possible (to not pollute outer namespaces) and generally, only pull in the specific symbols you need, not just the entire namespace.
In headers (that may get included by many users) you should generally refrain from the practice alltogether and instead prefer to always just use explicit namespace qualifications on types.
In a header file... the following example is evil. Never use using namespace... in the global scope of a header file. It forces a lot of unasked for symbols on the user that can cause very hard to fix problems if they clash with other headers.
#include <memory>
using my_namespace1::component1;
using my_namespace2::component2;
namespace my_application {
namespace platform_logs {
class backtrace_log {
//code that creates instances of my_namespace1::component1 and my_namespace2::component2
};
}
}
On the other hand this next example is fine, but to be used with caution. It only makes sense if you want to include all those symbols in your API. This is often the case with internal project name spaces but less likely with third party namespaces.
I would especially avoid even this with very large namespaces like std::.
#include <memory>
namespace my_application {
namespace platform_logs {
using my_namespace1::component1;
using my_namespace2::component2;
class backtrace_log {
//code that creates instances of my_namespace1::component1 and my_namespace2::component2
};
}
}
In your first example whenever you include
backtrace.h
in another file that file will also use those namesapces. So if by mistake someone wrote "blax" in a file where you included backtrace.h and "blax" also happened to be a class or function in you namespace, e.g.:
my_namespace1::component1::blax
the compiler might take his "blax" to mean "my_namespace1::component1::blax"
By placing the using namespace inside another namespace you simply include all those definitions into that namespace, in the previous example, if you went with version two of the code that collision wouldn't happen since "my_namespace1::component1::blax" would be included as my_application::platform_logs::blax.
Overall most coding guides would encourage you to:
a) Prefer to not ever do "using namespace" or at least use it just to shorten (e.g. using short_namespace = first_namespace::another_namepsace::last_namespace)
b) If you do "using namespace" do so in the source file (i.e .cpp or .c files), since the definitions in those files are not included
c) If you do "using namespace" in headers nest it in another namespace (like in your example) so that it doesn't "leak" into the scope of other file which include your header

What is the difference between using and include in c++?

I know that include is for classes and using is for some built-in stuff, like namespace std... When you include something, you can create objects and play around with them, but when you are "using" something, then you can use some sort of built-in functions. But then how am I supposed to create my own "library" which I could "use"?
Simply put #include tells the pre-compiler to simply copy and paste contents of the header file being included to the current translation unit. It is evaluated by the pre-compiler.
While using directive directs the compiler to bring the symbol names from another scope in to current scope. This is essentially put in effect by the compiler.
But then how am I supposed to create my own "library" which I could "use"?
Namespaces are something which are used for preventing symbol name clashes. And usually every library implementer will have their functionality wrapped up in one or many namespaces.
'include' basically does a copy-paste the value of a file to the location of the "include" line. This is used to make your source code (usually .c file) aware of a declaration of other source code (usually sits in .h file).
'using' basically tells the compiler that in the next code you are using something (usually a namespace) so you won't have to do it explicitly each time:
Instead of:
std::string a;
std::string b;
std::string c;
You could write:
using namespace std;
string a;
string b;
string c;
You can say both gives the same functionality but #include is not done by compiler where as using is done by compiler. In #include all the code is placed in file where #include is given where as namespace gives the definition of function and variables from one scope to another. If you have function with same name in two header files and both are included then there will be an error of redeclaration but you can use same name functions if they are from different namespaces.

#includes within a namespace, to "embed" prewritten stuff in namespace

BRIEF: is it ever safe to do
namespace Foo {
#include "bar"
}
Before you blithely say no, I think I have some rules that allow it fairly safely.
But I don't like them, since they require the includer to separately include all global scope headers needed. Although this mightr be tolerable, if we imagine including within a namespace to be just a special management feature.
And overall, externs and forward declarations just don't work well from within namespaces.
So I gues I am asking
a) What other gotchas
b) is there a better way
== A [[Header-only library]] ==
I like writing libraries. [[Header-only libraries and linker libraries]].
E.g.
#include "Valid.hpp"
defines a template Valid, for a simple wrapper type.
(Don't get bogged down in "You should use some standard library for this rather than your own. This is an exanple. I dunno if Boost or C++ have yet standardized this. I have been using wrappers since templates were added to C++.)
Also, let us say, it is a header only library, that defines, in Valid.hpp,
a print function
std::string to_string( const Valid& v ) {
std::ostringstream oss;
if( v.valid() ) { oss << v; }
else { "invalid"; }
return oss.str();
}
And because I think it is the right thing to do,
I have Valid.hpp include the headers it depends on:
Valid.hpp:
#include <iostream>
#include <sstream>
template<typename T>
class Valid {
private:
T value_;
bool valid_
...
};
...
std::string to_string( const Valid<T>& v ) { ...
So far, so good.
I can use Valid straightforwardly.
== Name collision - trying to use include within namespace to work around ==
But sometimes there is a collision.
Sometimes somebody else has their own Valid.
Namespaces to the rescue, right? But I don't want to change all of my existing code to use the namespace.
So, I am tempted, in a new project that has a collision, to do
namespace AG {
namespace Wrapper {
#include "lib/AG/Wrapper/Valid.hpp"
}
}
AG::Wrapper::Valid<T> foo_v;
...
PROBLEM: the headers included are no longer freestanding. Everything defined inside is no placed inside
namespace AG::Wrapper.
It's not hard to "fix".
Al we "must" do is include all the top level libraries that Valid.hpp depends on.
If they have include guards, they will not be re-included.
#include <iostream>
#include <sstream>
namespace AG {
namespace Wrapper {
#include "lib/AG/Wrapper/Valid.hpp"
}
}
AG::Wrapper::Valid<T> foo_v;
...
But it is no longer freestanding. :-(
Worse, sometimes the header-only library contains extern declarations and forward declarations of stuff outside itself.
These declarations get placed inside the namespace too.
In particular, if the extern declarayion is inside a function defined in the namespace.
I.e. sometimes we use extern and forward declarations, rather than included an entire header file.
These get included in the namespace.
Q: is there a better way?
== :: doesn't do it ==
Hint: :: doesn't do it. At least not all the time, not in gcc 4.7.2.
(Gcc's behavior in this has changed over time. Gcc 4.1.2 behaved differently.)
E.g.
Type var;
namespace Foo {
void bar() {
extern ::Type ::var;;
extern ::Type ::Foo::bar;
extern ::Type::foo ::bar; // see the ambiguity?
};
But it's not just the ambiguity.
int var;
namespace Foo {
void bar() {
extern int var;
};
works - Foo::bar'svar is equal to ::var.
But it only works because of the declaration outside the namespace.
The following doesn't work
header
int var;
cpp
namespace Foo {
void bar() {
extern int var;
}
}
although the following does:
header
int var;
cpp
void bar() {
extern int var;
}
}
Basically, what this amounts to saying is that
it is not a trivial refactoring to put functions inside a namespace.
Wrapping a namespace around a chunk of code,
whether or not it is #include'd,
is not a sufficient.
... at least not if there are extern or forward declarations.
And even if you
== Opinion against putting includes within namespaces ==
Stackoverflow folks seem to be against putting #includes inside namespaces:
E.g. How to use class defined in a separate header within a namespace:
... you should never write a #include inside a namespace. Where "never" means, "unless you're doing something really obscure that I haven't thought of and that justifies it". You want to be able to look at a file, and see what the fully-qualified names are of all the things in it. You can't do that if someone comes along later and sticks an extra namespace on the front by including from inside their namespace. – Steve Jessop Jan 6 '12 at 16:38
Overall question:
Is there any way, from deep within a namespace,
to say "and now here are some names that I am depending on from the outside world, not within the namespace."?
I.e. I would like to be able to say
namespace A {
void foo() {
// --- here is a reference to gloal scope extreren ...
I know this is an old question, but I want to give a more detailed answer anyway. Also, give a real answer to the underlying problem.
Here's just a few things that can go wrong if you include a header from within a namespace.
The header includes other headers, which are then also included from within the namespace. Then a different place also wants to include these headers, but from outside the namespace. Because the headers have include guards, only one of the includes actually goes in effect, and the actual namespace of the stuff defined in the headers suddenly subtly depends on the order you include other headers.
The header, or any of its included headers, expects to be in the global namespace. For example, standard library headers will very often (in order to avoid conflicts) refer to other standard stuff (or implementation details) as ::std::other_stuff, i.e. expect std to be directly in the global namespace. If you include the header from within a namespace, that's no longer the case. The name lookup for this stuff will fail and the header will no longer compile. And it's not just standard headers; I'm sure there are some instances of this e.g. in the Boost headers too.
If you take care of the first problem by ensuring that all other headers are included first, and the second problem by making sure no fully qualified names are used, things can still go wrong. Some libraries require that other libraries specialize their stuff. For example, a library might want to specialize std::swap, std::hash or std::less for its own type. (You can overload std::swap instead, but you can't do that for std::hash and std::less.) The way to do this is close your library-specific namespace, open namespace std, and put the specialization there. Except if the header of the library is included in arbitrarily deeply nested namespaces, it cannot close those namespaces. The namespace std it attempts to open won't be ::std, but ::YourStuff::std, which probably doesn't contain any primary template to specialize, and even if it did, that would still be the wrong thing to do.
Finally, things in a namespace simply have different names than things outside. If your library isn't header-only but has a compiled part, the compiled part probably didn't nest everything in the namespace, so the stuff in the library has different names than the stuff you just included. In other words, your program will fail to link.
So in theory, you can design headers that work when included within a namespace, but they're annoying to use (have to bubble up all dependencies to the includer) and very restricted (can't use fully qualified names or specialize stuff in another library's namespace, must be header-only). So don't do it.
But you have an old library that doesn't use namespaces, and you want to update it to use them without breaking all your old code. Here's what you should do:
First, you add a subdirectory to your library's include directory. Call it "namespaced" or something like that. Next, move all the headers into that directory and wrap their contents in a namespace.
Then you add forwarding headers to the base directory. For each file in the library, you add a forwarder that looks like this:
#ifndef YOURLIB_LEGACY_THE_HEADER_H
#define YOURLIB_LEGACY_THE_HEADER_H
#include "namespaced/the_header.h"
using namespace yourlib;
#endif
Now the old code should just work the way it always did.
For new code, the trick is not to include "namespaced/the_header.h", but instead change the project settings so that the include directory points at the namespaced subdirectory instead of the library root. Then you can simply include "the_header.h" and get the namespaced version.
I don't think it's safe. You put all your includes into the namespace Foo...
Imagine some of your includes include something from the std namespace... I cannot imagine the mess !
I wouldn't do that.
Header files are not black boxes. You can always look at a header you're including in your project and see if it is safe to include it inside a namespace block. Or better yet, you can modify the header itself to add the namespace block. Even if the header is from a third-party library and changes in a subsequent release, the header you have in your project won't change.

Scope of DataType declared in Namespace

Sample.h
namespace Testing
{
enum Type
{
DATA = 0,
MORE_DATA
};
}
Now in Sample2.h, using the same namespace, can I access the DataType defined in Sample.h, without including it?
namespace Testing
{
Type test;
}
The question has come up, because I have files that implement this, and seem to build with no problem.
Another user is trying to build, but reports that he has to #include "Sample.h" in Sample2.h in order to build.
Most likely the files build because some earlier include file is including Sample.h for you. When the earlier include file is omitted (or moved after Sample2.h) the files will no longer compile.
Forward enum declarations are not supported in most current compilers. It is a planned feature of up coming C++0x. You can create pointers to Type probably, but cannot instantiate, this is compatible with other types (structs and classes) as well.
Ow, my bad, I saw it wrong i guess. Anyway, read the others and read this as well. Headers are not compiled stand alone. Therefore, if you don't include a required heading in your header and included that in the cpp file you will not run into any errors. As long as all the cpp files contain both headers with the required order there will be no problems at all. However, this is not a good idea, it is best to include any necessary files within your header and use header guards to ensure they are not added twice. I hope this makes sense.
Yes, you will need to include Sample.h within Sample2.h. The definition of Type is not visible to the compiler within Sample2.h simply because the namespace name is the same within the 2 files.
The only thing you gain by having the same namespace names in the 2 files is that Type does not need to have its namespace stated explicitly in Sample2.h. For instance, if the 2 namespaces were not the same:
Sample.h
namespace Testing
{
enum Type
{
DATA = 0,
MORE_DATA
};
}
Sample2.h
#include "Sample.h"
namespace Testing1
{
Testing::Type test;
}

Why we can't include std headers within a namespace in C++

The following code will cause compile errors in g++4.4:
// File test.cpp
namespace A
{
#include <iostream>
}
int main()
{
return 0;
}
I have this requirement because some third party library comes without namespace protected, and if I directly include these headers, my namespace is polluted.
As a result, I tried to create namespaces for those libraries, but if the library includes some "std headers" the above approach will fail.
Can anybody help?
Thank You!
I believe 17.4.2.1 [lib.using.headers] forbids including standard library headers in a namespace :
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 to any of the entities it declares or first defines in that
translation unit.
I don't think there is anything you can do besides filing a request to the library author.
This approach will most likely lead you to trouble. You could approach the problem by manually including each such standard header before entering the namespace, and the include guards would take care of not re-including the header inside the namespace.
That would take care of your current error, but it would on the other hand break too many other things --if the library is precompiled then the symbols used in your code and the symbols in the binary library would be different symbols (libname::foo() used in your code, ::foo() defined in the binary). Even if the library is header only, any fully qualified access to the library within the library itself would break (void foo() { ::bar(); } where foo and bar are inside the library).
A valid approach that you might want to try (even if cumbersome, and requiring real work) would be writting a wrapper that is within it's own namespace, and uses the library. Then include your wrapper instead of the actual library headers.
My advice, on the other hand, would be ignoring the problem altogether. Declare your own objects within your namespaces and that would take care of the possible name collisions. As long as you keep away from using namespace statements you will be fine.
Use fully qualified names when using calls to standard libraries like std::cout instead of writing using namespace std;. This way, both can coexist.