We've got a reasonable sized C++ application that's pretty old at this stage, so it's got a few quirks.
One of these quirks is in how it deals with C++ compilers that use a pre-standisation standard library. There's one header file that's supposed to resolve any differences between a standards compliant compiler and this one non-compliant compiler. For various reasons we can't / don't want to stop supporting this compiler.
#include <vector>
#include <set>
#if defined(NO_STD_LIB)
#include <iostream.h>
#else
#incude <iostream>
using std::string;
using std::cout;
using std::vector;
using std::cout;
#endif
You use this as follows
#include stl.h
int main() {
vector<string> foo;
.....
return 0;
}
There are 2 main issues with this approach:
Each compilation unit that includes std.h has to compile lots of un-needed code (and we're trying to reduce compile times as much as possible at the minute)
The global namespace gets polluted with pretty much everything that would normally be in the std namespace.
I really would like to address both of these points as part of a code cleanup project. The first one really is the more important reason for doing this.
As we have to support this old compiler then our code will always have to avoid clashing names with things that it exposes in it's standard lib, so point 2 isn't really relevant, though I'd like to see a solution that works when / if we can finally drop support for it.
My idea so far is to break up the super header into a set of smaller headers. e.g. stl_vector, stl_iostream, stl_set, etc. This way we can only include the parts of the standard library that we're interested in. These filenames follow the pattern of the std headers, but with an easily searched for prefix. So when the time comes to dump the offending compiler, it'll be simple to search for the prefix and remove it.
I think that will fix issue 1 easily enough.
My real problem is fixing issue 2. I thought of doing someting like this
#if defined(NO_STD_LIB)
#include <iostream.h>
#define std
#else
#include <iostream>
then we could code as follows:
#incude "stl_iostream"
int main() {
std::string foo("bar");
std::cout << foo << std::endl;
}
And that almost worked. Where there was no standard namespace the #define std made std::string decompose into ::string and life was good.
Then I tried this with a .cc file that used the dreaded "using namespace std;" and I get a compile error because that becomes "using namespace ", so that obviously won't work.
Now obviously I could ban people from writing "using namespace std;", but as much as it should be avoided in headers, it's sometimes useful in .cc files where you're making heavy use of lots of STL classes.
So, finally, to the question. Is there a standard idiom for dealing with this issue. Or if there isn't a standard way to deal with this, then what tricks do you use to support compilers that use a pre-standard standard library.
I've thought of using pre-compiled headers to solve the compilation speed issue, but we target different compilers and the effort of getting this working across all of them may mean its not worth our time doing it.
Answers that advise me to drop the non-conforming compiler may be popular, but won't be accepted as this is something that we can't do just now.
You can try:
#if defined(NO_STD_LIB)
namespace std {
using ::string;
using ::cout;
using ::vector;
using ::cout;
}
#endif
Then std::string will work.
It would have been much better if the using namespace ::; directive existed in the language; however it doesn't.
Related
I have seen codes with using namespace std;. Does it mean that if we use this then we don't have to include header files in the code or if we don't use namespaces, does it mean that we have to use std:: before every function, class?
You have to include header files and use namespaces.
The namespaces are contained in the header files, io streams like cin,cout are contained in the namespaces.So, only if you include the header file, namespace can be used. Without using namespace std, You have to use scope resolution operator every time you use those functions.
using namespace std; means that all names from std namespace can be used without specifying their namespace explicitly (with std:: prefix). That is, after using namespace std;, both string and std::string are valid. Without using namespace std;, only std::string would work.
Header files still must be included.
Note that usage of using namespace is often discouraged as it populates your code with all names from that namespace, and conflicts may occur.
using namespace std;
Is not really an ideal practice I would apply in a professional code base. The reason is that it practically "opens up" std namespace (packages in Java if you like) where you are probably doing "Hello world"ish programming i.e. not so severe as RT Embedded, Mission Critical, or Safety Critical. For example, I work in Interservice/Industry Training and Simulation where things are often safety/mission critical; people will propbably have a quiet word with me if I was using multiple namespaces so openly. It's not really about the size of your program, it is more about Good practice. Yes, if you have so many things to use from std namespace, then probably you can simply use it. A compromise, and also what I sometimes do, is:
using std::endl;
using std::string;
using std::cout;
using std::cin;
// And something like that
This "exposes" the ones that you will need for this scope and still lets you use:
string myStr;
cout << "Some cout" << endl;
Like what you mentioned in your question. Why not try that?
A "Good bit" of all is that if you follow the approach I mentioned, it also "Upgrade" your level of knowlege in C++ namespaces and possible STLs.
I know some people will say "Well that is stil hard work" but to me it is a good compromise, up to a point. :)
DON'T FORGET TO ADD THE NECESSARY HEADER FILES PLEASE :-)
Inherited a slew of legacy C code, and am in the process of porting it to compile on Linux with GCC (g++). Since we are going to be using C++ in the future and I'm fixing the "custom" library header files anyways (and compiler warnings), is it safe to update the old C headers to use the newer C++ style ones.
So things like
#include <cstdlib>
Instead of
#include <stdlib.h>
To my knowledge the only difference between the two is that cstdlib has things in the std:: namespace.
Would anything make this a bad idea?
Your code may change in very subtle ways, due to the fact that the C++ standard headers use overloading where C used different names. This is most likely to cause trouble with cmath.
stdlib.h isn't going anywhere, so feel free to keep using it.
For example, compare:
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <math.h>
int main(void)
{
double x = -2;
cout << (3/abs(x)) << endl;
return 0;
}
The results before and after switching to C++ headers are very different, even though the exact same C++ compiler and options are used in both cases.
They're exactly the same (on most systems) except for the namespace thing.
I've encountered this issue while trying to port my C++ source code from HP-UX to Linux. When I try to compile the C++ source code on Linux, what happens is that it complains that components (from the standard C++ library) don't exist. Placing the line using namespace std; at the top of the source code seems to fix the problem. When I try to recompile the code on HP-UX, the aCC compiler complains that only namespace names are valid here ( it doesn't consider std a valid namespace ). I was wondering if there was a way to get around this issue so that the source code is binary compatible with both HP-UX's long deprecated C++ compiler and LINUX's GCC compiler.
This sucks, but you can do this:
#ifndef __HP_aCC
using namespace std;
#endif
Defines from here, and I have no way to verify.
You could use pre-proccessors to check for the OS and whether or not to include namespace std; So if your OS is not HP aCC, it doesn't includes std, otherwise it does. Like so:
#ifndef __HP_aCC
using namespace std;
#endif
or if you want to check for linux and win and only use namespace std if its those OS; you can also do it like this:
#if defined(WIN32) || defined(LINUX)
using namespace std;
#endif
Hope that helped!
You should be able to do this, if you really don't want #ifdef's:
namespace std {}
using namespace std;
That is, create or extend the std namespace. On Linux, it will extend, and on HP-UX, it will create. In either case, the using will be valid.
However, if the HP-UX compiler is as old as you say, then the source code for including C++ header files is likely the old style:
#include <iostream.h>
Instead of the modern style:
#include <iostream>
If you have a solution around this issue, then you are probably using conditional compilation someplace in your code. If you have already localized these kind of platform specific decisions into a single place in your code, then that would be the place to add code to only do using namespace std for those platforms that need it.
Ensure that you're including the correct headers. C++ doesn't define which standard headers might include other standard headers, so implementations behave differently when you make use of indirect includes. So just verify that everything you need to include is included directly.
Don't use using namespace std; just fully qualify the names you use, or use using declarations that call out the specific components you need.
using std::string;
string s; // no need for using namespace std
You can use platform-specific constants like LINUX or WIN32, to add or not the line using namespace std. The usual way to do this is to make (or, more often, to generate) a config.h file, defining aliases for platform-specific type-names that you use.
Boost's C99 stdint implementation is awfully handy. One thing bugs me, though. They dump all of their typedefs into the boost namespace. This leaves me with three choices when using this facility:
Use "using namespace boost"
Use "using boost::[u]<type><width>_t"
Explicitly refer to the target type with the boost:: prefix; e.g., boost::uint32_t foo = 0;
Option № 1 kind of defeats the point of namespaces. Even if used within local scope (e.g., within a function), things like function arguments still have to be prefixed like option № 3.
Option № 2 is better, but there are a bunch of these types, so it can get noisy.
Option № 3 adds an extreme level of noise; the boost:: prefix is often ≥ to the length of the type in question.
My question is: What would be the most elegant way to bring all of these types into the global namespace? Should I just write a wrapper around boost/cstdint.hpp that utilizes option № 2 and be done with it?
Also, wrapping the header like so didn't work on VC++ 10 (problems with standard library headers):
namespace Foo
{
#include <boost/cstdint.hpp>
namespace boost_alias = boost;
}
using namespace Foo::boost_alias;
EDIT: I guess another option is to use the preprocessor to make it work on VC 10? Taking the snippet above:
#ifndef FOO_HPP_INCLUDED
#define FOO_HPP_INCLUDED
#if _MSC_VER >= 1600 /*VC++ 10*/ || defined USE_NATIVE_STDINT_HEADER
#include <stdint.h>
#else
namespace cstdint_wrapper
{
#include <boost/cstdint.hpp>
namespace boost_alias = boost;
}
using namespace cstdint_wrapper::boost_alias;
#endif
#endif
Less work, I guess?
I just use C99's stdint.h (it's actually now in VS 2010). For the versions of Visual C/C++ that don't include it, I use a public domain version from MinGW that I modified to work with VC6 (from when I had to work in VC6):
http://snipplr.com/view/18199/stdinth/
There are a couple other options you might consider in this SO question: C99 stdint.h header and MS Visual Studio
If you'd like to continue using boost/cstdint.hpp, I'd say that the suggestion of implementing a wrapper header that brings the types into the global namespace would be the way to go.
Does boost/cstdint.hpp provide anything I should know about that isn't in stdint.h?
Your idea of writing a wrapper header that implements option 2 is definitely the better of those three options.
What I'd suggest, though, is a slight variant: Put those using declarations within another namespace, such as cstdint or something; then, you have the option if putting using cstdint; in your own code or explicitly specifying cstdint:: on the particular uses.
If you included directly the file you will be forced to prefix it with std::. So the question is, which option would you take in this case. What would you do with the other types introduced by Boost? Would you prefix them with boost:: or not?
The fist one is clearly a bad option.
You can implement option two using your my_cstdint.hpp file
#include <boost/cstdint.hpp>
using boost::uint32_t;
...
and include my_cstdint.hpp in your application. But in my opinion it is a bad idea to add new symbols on the root namespace, you can get more conflicts as the types can be already defined by for example the stdint.h C file.
Even if the third option use a lot of characters, namespaces are there for this purpose. boost::uint32_t will be defined to the correct type depending on your toolset, so just use it, as you would use std::uint32_t.
I personally always use option 3. If things are too long, then you can use typedefs to reduce the amount of code.
Why do we need both using namespace and include directives in C++ programs?
For example,
#include <iostream>
using namespace std;
int main() {
cout << "Hello world";
}
Why is it not enough to just have #include <iostream> or just have using namespace std and get rid of the other?
(I am thinking of an analogy with Java, where import java.net.* will import everything from java.net, you don't need to do anything else.)
using directives and include preprocessor directives are two different things. The include roughly corresponds to the CLASSPATH environment variable of Java, or the -cp option of the java virtual machine.
What it does is making the types known to the compiler. Just including <string> for example will make you able to refer to std::string :
#include <string>
#include <iostream>
int main() {
std::cout << std::string("hello, i'm a string");
}
Now, using directives are like import in Java. They make names visible in the scope they appear in, so you don't have to fully qualify them anymore. Like in Java, names used must be known before they can be made visible:
#include <string> // CLASSPATH, or -cp
#include <iostream>
// without import in java you would have to type java.lang.String .
// note it happens that java has a special rule to import java.lang.*
// automatically. but that doesn't happen for other packages
// (java.net for example). But for simplicity, i'm just using java.lang here.
using std::string; // import java.lang.String;
using namespace std; // import java.lang.*;
int main() {
cout << string("hello, i'm a string");
}
It's bad practice to use a using directive in header files, because that means every other source file that happens to include it will see those names using unqualified name lookup. Unlike in Java, where you only make names visible to the package the import line appears in, In C++ it can affect the whole program, if they include that file directly or indirectly.
Be careful when doing it at global scope even in implementation files. Better to use them as local as possible. For namespace std, i never use that. I, and many other people, just always write std:: in front of names. But if you happen to do it, do it like this:
#include <string>
#include <iostream>
int main() {
using namespace std;
cout << string("hello, i'm a string");
}
For what namespaces are and why you need them, please read the proposal Bjarne Stroustrup gave 1993 for adding them to the upcoming C++ Standard. It's well written:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/N0262.pdf
In C++ the concepts are separate. This is by design and useful.
You can include things that without namespaces would be ambiguous.
With namespaces you can refer to two different classes that have the same name. Of course in that case you would not use the using directive or if you did you would have to specify the namespace of the other stuff in the namespace you wanted.
Note also that you don't NEED the using - you can just used std::cout or whatever you need to access. You preface the items with the namespace.
In C++ #include and using have different functions.
#include puts the text of the included file into your source file (actually translation unit), namespaces on the other hand are just a mechanism for having unique names so that different people can create a "foo" object.
This comes from C++ not having the concept of a module.
Keep in mind that namespaces in C++ are open, that means that different files can define different parts of the same namespace (sort of like .NET's partial classes).
//a.h
namespace eg {
void foo();
}
//b.h
namespace eg {
void bar();
}
The include is defining the existence of the functions.
The using is making it easier to use them.
cout as defined in iostream is actually named "std::cout".
You could avoid using the namespace by writing.
std::cout << "Hello World";
These keywords are used for different purposes.
The using keyword makes a name from a namespace available for use in the current declarative region. Its mostly for convenience so that you do not have to use the fully qualified name all the time. This page explains it in some detail.
The #include statement is a pre processor directive and it tells the preprocessor to treat the contents of a specified file as if those contents had appeared in the source program at the point where the directive appears. That is, you can think of this statement as copying the included file into the current one. The compiler then compiles the entire file as if you wrote all the code in one big file.
As pointed out, C++ and Java are different languages, and do somewhat different things. Further, C++ is more of a 'jest grew' language, and Java more of a designed language.
While using namespace std; isn't necessarily a bad idea, using it for all namespaces will eliminate the whole benefit. Namespaces exist so that you can write modules without regard to name clashes with other modules, and using namespace this; using namespace that; can create ambiguities.
I think the other answers are missing the point slightly. In all of C++, Java and C#, the using/import thing is entirely optional. So that's not different.
And then you have to do something else to make code be visible anyway, in all three platforms.
In C++, you minimally have to include it into the current translation unit (good enough for many implementations of vector, string, etc.), often you have to add something to your linker as well, although some libraries do that automatically based on the include (e.g. boost when building on Windows).
And in C# you have to add a reference to the other assembly. That takes care of the equivalent of includes and link settings.
And in Java you have to ensure the code is on the classpath, e.g. adding the relevant jar to it.
So there are very closely analogous things required on all three platforms, and the separation between using/import (a convenience) and actual linkage resolution (a requirement) is the same in all three.
You need to understand namespaces if you want to truly understand this.
With include you are just including the header file.
With using namespace you are declaring you are using a given namespace that contains stuff such as cout. so if you do this:
using namespace std;
to you use cout you can just do
cout << "Namespaces are good Fun";
instead of:
std::cout << "Namespaces are Awesome";
Note that if you do not #include <iostream> you won't be able to use neither std::cout nor cout in your declarations and so forth because you're not including the header.
One liner (not that this is something new :)):
using std allows you to omit std:: prefix, but you cannot use cout at all without iostream.
Even Stroustrup refers to the #include mechanism as somewhat hackish. However it does make separate compilation much easier (ship compiled libraries and headers instead of all source code).
The question really is "why did C++ -- after it already had the #include mechanism -- add namespaces?"
The best example I know of about why #include isn't enough comes from Sun. Apparently Sun developers had some trouble with one of their products because they had written a mktemp() function that happened to have the same signature as a mktemp() function that was included through from a file that was itself included through a header the project actually wanted.
Of course the two functions were not compatible, and one could not be used as a substitute for the other. On the other hand, the compiler and linker did not realize this when building the binary, and sometimes mktemp() would call one function, and sometimes it would call another, based on the order different files were compiled or linked.
The problem stems from the fact that C++ was originally compatible with -- and essentially piggy-backed on top of -- C. And C has only a global namespace. C++ solved this problem -- in code that is not compatible with C -- through namespaces.
Both C# and Java (1) have a namespace mechanism (namespace in C#, package in Java), (2) are usually developed through IDEs that handle referring to binaries for the developer, and (3) don't allow freestanding functions (a class scope is something of a namespace, and reduces the risk of polluting the global namespace) so they have a different solution to this problem. However, it is still possible to have some ambiguity regarding which method you're calling (say, a name clash between two interfaces that a class inherits), and in that case all three languages require the programmer to clearly specify which method they're actually looking for, usually by prepending the parent class/interface name.
In C++, the include directive will copy and paste the header file into your source code in the preprocessing step. It should be noted that a header file generally contains functions and classes declared within a namespace. For example, the <vector> header might look similar to something like this:
namespace std {
template <class T, class Allocator = allocator<T> > class vector;
...
}
Supposing you need to define a vector in your main function, you do #include <vector> and you have the piece of code above in your code now:
namespace std {
template <class T, class Allocator = allocator<T> > class vector;
...
}
int main(){
/*you want to use vector here*/
}
Notice that in your code the vector class is still located in the std namespace. However, your main function is in the default global namespace, so simply including the header will not make the vector class visible in global namespace. You have to either use using or do prefixing like std::vector.