1

C++ ISO draft 2020(6.4.6 Namespace Scope) quotes in the first paragraph(bolded by me):

The declarative region of a namespace-definition is its namespace-body . Entities declared in a namespace-body are said to be members of the namespace, and names introduced by these declarations into the declarative region of the namespace are said to be member names of the namespace. A namespace member name has namespace scope. Its potential scope includes its namespace from the name’s point of declaration (6.4.2) onwards; and for each using-directive (9.8.3) that nominates the member’s namespace, the member’s potential scope includes that portion of the potential scope of the using-directive that follows the member’s point of declaration.

I thought it wouldn't have a difference between unnamed and named namespace, but the following code has problems:

#include <iostream>
namespace A {int a = 1;}
namespace {int b = 1;}
void main() {
    std::cout << a; // identifier "a" is undefined
    std::cout << b;
}

Cppreference gives the reason for this problem:

The potential scope of a name declared in an unnamed namespace or in an inline namespace includes the potential scope that name would have if it were declared in the enclosing namespace.

But based on my understanding of the first quote of this question, this error shouldn't occur. What happened here?

6
  • namespace { /*body*/ } behaves, by definition, as namespace UniqueName {} using namespace UniqueName; namespace UniqueName { /*body*/ } where UniqueName is some invented identifier unique to the translation unit. The difference between the two namespaces in your example is this implicit using directive. Commented Oct 17, 2021 at 3:30
  • 1
    If in your example a could be found by unqualified lookup, without specifying its namespace, namespaces would have been rather pointless. Why do you believe the error shouldn't occur? How do you arrive at this conclusion from the passage you quote? Commented Oct 17, 2021 at 3:32
  • @IgorTandetnik I think the problem was my interpretation of the "onwards" word. I understood it as from the point of declaration, until (well, until everything) to the end of the translation unit, but the onward is until the end of the namespace body, right? Commented Oct 18, 2021 at 2:05
  • 1
    "includes its namespace from the point of declaration onwards". Not the whole source file onwards, but the parts of it that lie within the namespace it's a member of. "End of namespace body" is not well-defined, as a namespace may be defined in bits and pieces: namespace N { int x;} namespace N {int y;} Commented Oct 18, 2021 at 2:42
  • 1
    The reason names declared in unnamed namespaces are visible in the enclosing namespace is the aforementioned implicit using directive. So the other part of your quote comes into play: "and for each using-directive (9.8.3) that nominates the member’s namespace, the member’s potential scope includes that portion of the potential scope of the using-directive..." Commented Oct 18, 2021 at 2:47

1 Answer 1

1

I thought it wouldn't have a difference between unnamed and named namespace

Both a and b are available in main. But a cannot be accessed without scope resolution. The documentation refers to "potential scope", "actual scope", and "scope", plus block/class/function/namespace scope, it can get confusing.

You can see the similarity of named and un-named namespace with this code:

class foo
{
    std::string str;
public:
    foo(const char* s) { str = s; cout << str << " foo()\n"; }
    ~foo() { cout << str << " ~foo()\n"; }
};

namespace named { foo a("named"); }
namespace { foo b("unnamed"); }
int main()
{
    cout << "start\n";
    named::a;
    b;
    cout << "end\n";
    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.