Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there only one unnamed namespace per compilation unit?

I have inherited a horrible bit of legacy code which includes about 1000 lines of utility class definition that needs to appear before the "real" code in a source file. To avoid clashes with other modules that might also have associated legacy classes, I have put the utility class into an unnamed namespace:

namespace {
    class OldUtils {
        OldUtils();
        int foo();
        double bar();
    };

    OldUtils::OldUtils() {
        // hundreds of lines
    }

    int OldUtils::foo() {
        // hundreds more lines
    }

    ...
}

class ActuallyInteresting {
    // uses OldUtils
};

But I would prefer to have the ActuallyInteresting code that people will be (actually) interested in near the top of the file, e.g. starting on line 50, than right at the bottom e.g. starting on line 1000. Splitting the horrid utility class into a separate compilation unit isn't an option, for higher-level reasons I won't go into!

So I am wondering if it is possible to put the short class declaration -- without method definitions -- in an unnamed namespace at the top of the file, and the much longer method definitions in another unnamed namespace at the bottom:

namespace {
    class OldUtils {
        OldUtils();
        int foo();
        double bar();
    };
}

class ActuallyInteresting {
    // uses OldUtils
};

namespace {
    OldUtils::OldUtils() {
        // hundreds of lines
    }

    int OldUtils::foo() {
        // hundreds more lines
    }

    ...
}

Will these two "separate" unnamed namespaces be treated as the same scope within the compilation unit, or will different unique namespaces be generated for each? Does the standard have anything to say about this?

like image 265
andybuckley Avatar asked Apr 27 '16 12:04

andybuckley


People also ask

What is an unnamed namespace?

A namespace with no identifier before an opening brace produces an unnamed namespace. Each translation unit may contain its own unique unnamed namespace. The following example demonstrates how unnamed namespaces are useful.

Can you use multiple namespaces?

A namespace is a declarative region that provides a scope to the identifiers (names of functions, variables or other user-defined data types) inside it. Multiple namespace blocks with the same name are allowed. All declarations within those blocks are declared in the named scope.

What does an unnamed namespace do in C++?

Unnamed Namespaces They are directly usable in the same program and are used for declaring unique identifiers. In unnamed namespaces, name of the namespace in not mentioned in the declaration of namespace. The name of the namespace is uniquely generated by the compiler.

How many namespaces are there in C++?

There are three main namespaces. The ISO C++ standards specify that "all library entities are defined within namespace std." This includes namespaces nested within namespace std , such as namespace std::chrono . Specified by the C++ ABI.


1 Answers

Will these two "separate" unnamed namespaces be treated as the same scope within the compilation unit, or will different unique namespaces be generated for each? Does the standard have anything to say about this?

Yes, they will be treated as same within the compilation unit. And the standard does have something to say....

Quoting the latest standard draft... (emphasis are mine)

$7.3.1.1 An unnamed-namespace-definition behaves as if it were replaced by

inlineopt namespace unique { /* empty body */ }
using namespace unique ;
namespace unique { namespace-body }

where inline appears if and only if it appears in the unnamed-namespace-definition and all occurrences of unique in a translation unit are replaced by the same identifier, and this identifier differs from all other identifiers in the translation unit

Compile this short program, your compiler should complain of variable redeclaration...

namespace { int c = 0; }
namespace { double c = 8; }

int main(){ ++c; }

However, to access variables in an unnamed namespace, you use the regular way of accessing global variables... Hence this will work.

namespace { int c = 0; }
namespace { void f(){ c = 8; } }

int main(){ ++c; }
like image 135
WhiZTiM Avatar answered Sep 24 '22 01:09

WhiZTiM