CS253: Software Development with C++

Spring 2018

Namespaces

See this page as a slide show

CS253 Namespaces

Overview

Namespace qualifiers

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.

General using

To embrace an entire namespace:

#include <iostream>
using namespace std;
int main() {
    cout << "gamma" << endl;
}
gamma

Specific using

To import just one symbol:

#include <iostream>
using std::cout;
int main() {
    cout << "delta" << endl;
}
c.cc: In function 'int main()':
c.cc:4:24: error: 'endl' was not declared in this scope
c.cc:4:24: note: suggested alternative:
In file included from /usr/local/gcc-6.3.0/include/c++/6.3.0/iostream:39:0,
                 from c.cc:1:
/usr/local/gcc-6.3.0/include/c++/6.3.0/ostream:590:5: note:   'std::endl'

The global namespace

C Compatibility

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‽

C Compatibility

The file cmath looks something like this:

// This is cmath
namespace std {
    #include <math.h>
}

This avoids duplication of information.

Similar names

Don’t confuse these:

Classes are closed

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:7: error: redefinition of 'class Foo'
c.cc:1:7: error: previous definition of 'class Foo'

Namespaces are open

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 closed

However, 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.

Nested namespaces

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

The anonymous namespace

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.

Namespace aliases

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();

Symbol Resolution & Namespace Ambiguity

What about conflicts? Consider two libraries:

Mathematics functionsMorality functions
cos(radians)karma(action)
tan(radians)fasting()
sin(radians)sin(type)

Uh, oh! Each library has a sin() function!

Ambiguity

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.

Solutions

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);

Ambiguity example

#include <iostream>
using namespace std;
int dec = 10;
int main() {
    cout << dec << "°F\n";
    return 0;
}
c.cc: In function 'int main()':
c.cc:5:13: error: reference to 'dec' is ambiguous
c.cc:3:5: note: candidates are: int dec
In file included from /usr/local/gcc-6.3.0/include/c++/6.3.0/ios:42:0,
                 from /usr/local/gcc-6.3.0/include/c++/6.3.0/ostream:38,
                 from /usr/local/gcc-6.3.0/include/c++/6.3.0/iostream:39,
                 from c.cc:1:
/usr/local/gcc-6.3.0/include/c++/6.3.0/bits/ios_base.h:1016:3: note:            
        std::ios_base& std::dec(std::ios_base&)

Ambiguity example solutions

#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

User: Guest

Check: HTML CSS
Edit History Source

Modified: 2018-04-24T16:55

Apply to CSU | Contact CSU | Disclaimer | Equal Opportunity
Colorado State University, Fort Collins, CO 80523 USA
© 2018 Colorado State University
CS Building