std
, pronounced “standard”,
contains stuff defined by the C++ standard.
boost
namespace.
Namespace qualifiers look like class qualifiers:
#include <iostream> int main() { std::cout << "alpha" << std::endl; }
alpha
Use a ::
prefix to access the global namespace:
int alpha = 42; int main() { int beta = 17; std::cout << beta + ::alpha << '\n'; }
59
Note that beta
is not in the global namespace.
using
To embrace an entire namespace:
#include <iostream> using namespace std; int main() { cout << "gamma" << endl; }
gamma
using namespace std;
is evil, and
litter their code with std::
uses.
using
To import just one symbol:
#include <iostream> using std::cout; int main() { cout << "delta" << endl; }
c.cc:4: error: 'endl' was not declared in this scope
::
.
main
.
This is a valid C program. Compatibility demands that it be a valid C++ program, as well.
#include <stdio.h> #include <math.h> int main() { printf("The square root of ten is %f\n", sqrt(10.0)); }
The square root of ten is 3.162278
But, what about namespaces‽
<math.h>
puts symbols such as sqrt
into the global namespace,
since that’s where C programs expect them.
<cmath>
puts the same symbols into the std
namespace.
The file cmath
looks something like this:
// This is cmath namespace std { #include <math.h> }
This avoids duplication of information.
Don’t confuse these:
<string.h>
puts strlen
, strcpy
, … into the global namespace.
<cstring>
puts strlen
, strcpy
, … into the std
namespace.
<string>
puts the C++ string
class into the std
namespace.
Once you’ve defined a class, you can’t add to it—it’s closed. Consider:
class Foo { public: int a,b,c; }; class Foo { public: int d; }; int main() { }
c.cc:6: error: redefinition of 'class Foo'
On the other hand, you can add to a namespace—it’s open. Consider:
namespace Math { constexpr double PI = 3.14159; } namespace Math { constexpr double E = 2.71828; } int main() { cout << Math::PI * Math::E << '\n'; }
8.53972
std
is closedHowever, the C++ standard forbids you adding anything to the
namespace std
, so it’s effectively closed, anyway.
Generally, compilers won’t stop you, because they have to allow
the implementation to put things into std
, and it’s difficult
to differentiate between you and the implementation, but it’s still
against the rules, so don’t do it.
Namespaces can be nested.
namespace Pika { constexpr int public_value = 123; namespace Private { constexpr int none_of_your_business = 456; } } int main() { cout << Pika::public_value << '\n'; }
123
If you don’t give your namespace a name, that’s an anonymous namespace.
The compiler makes up a name and does an implicit using
declaration:
namespace { int foo; }
It’s pretty much the same as:
namespace UNIQUE_NAME_42258107985915 { int foo; } using namespace UNIQUE_NAME_42258107985915;
It’s intended to replace top-level static
declarations.
Long namespace names are good. For example, you wouldn’t want
a namespace called HP
—that’s a popular abbreviation:
So, the library implementors can define the namespace name to be
Hewlett_Packard
, and the user can create an easy-to-type alias:
namespace HP = Hewlett_Packard; value = HP::handy_function();
What about conflicts? Consider two libraries:
Mathematics functions | Morality functions |
---|---|
cos( radians) | karma( action) |
tan( radians) | fasting() |
sin( radians) | sin( type) |
Uh, oh! Each library has a sin()
function!
What will this do?
using namespace Math; using namespace Morality; a = sin(b);
It will just plain fail. An unqualified sin
is ambiguous, because
there are two versions available. There is no priority order.
Also, the global namespace has no priority advantage, either.
You can explicitly disambiguate:
using namespace Math; using namespace Morality; a = Morality::sin(b);
Or, you can only bring in the functions that you use:
using Math::tan; using Morality::sin; a = sin(b);
#include <iostream> using namespace std; int dec = 10; int main() { cout << dec << "°F\n"; return 0; }
c.cc:5: error: reference to 'dec' is ambiguous
#include <iostream> using namespace std; int dec = 10; int main() { cout << ::dec << "°F\n"; return 0; }
10°F
#include <iostream> using std::cout; int dec = 10; int main() { cout << dec << "°F\n"; return 0; }
10°F