3

In C++14 standard, [basic.scope.hiding], paragraph 2 (3.3.10.2), says:

A class name or enumeration name can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.

I'm disturbed by the wording "same scope". Indeed, in the following snippet of code, what are the cases where the class C and the variable C are declared in the same scope?

namespace case_1 {
    int C;
    class C;
    // Here C refers to variable
}

namespace case_2 {
    class C;

    namespace nested {
        int C;
        // Here C refers to variable
    }
}

namespace case_3 {
    int C;

    namespace nested {
        class C;
        // Here C refers to class
    }
}

namespace case_4 {
    enum Enum { A, B, C };
    class C;
    // Here C refers to enumerator
}

Hypothesis 1: "same scope" means "same block"

If we adhere to this hypothesis, the case 1 should be concerned by the rule 3.3.10.2. What about case 2? I guess it is covered by rule 3.3.10.1:

A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class.

Also, this hypothesis explains well the case 3 where the class name hides the variable name (and not the inverse) but can't explain the case 4. Indeed, C enumerator is declared in a different block than C class but the class is still hided.

Hypothesis 2: "declared in the same scope" means "have exactly the same scope"

If that hypothesis is true, no cases described in my code are concerned by the rule because it impossible for two name to have the exact same scope. Even the variable in case_1 has a different scope that the class. Indeed, the scope of the variable name starts after its declaration so before the class name.

Hypothesis 3: "declared in the same scope" means "one of the name is declared inside the scope of the other"

If this hypothesis is true, all the cases describe above should be covered by the rule 3.3.10.2. Indeed, in case_1 and case_3, C class is declared in the scope of C variable; in case_2, C variable is declared in the scope of C class; and, in case_4, C class is declared in the scope of C enumerator. However, the case_3 doesn't follow the rule because it is the variable who should "win" and stay visible.


As you can see, each of my hypothesis have a drawback and I really don't understand what the standard exactly means by "same scope" in that paragraph.

Community
  • 1
  • 1
Pierre
  • 1,942
  • 3
  • 23
  • 43
  • 2
    There are no *hypothesis* related to language standards and definitions in coding. And, trying to sort things out with the *scientific method*, does not apply. It all boils down to knowing either (1) the answer, or (2) guessing. Coding by guessing is bad Juju... (your question is very good though `:)` – David C. Rankin Oct 03 '19 at 14:10
  • @DavidC.Rankin Actually ppl do that all the time in all sorts of tribunals. – curiousguy Oct 04 '19 at 00:02
  • Well, you may have taken my comment wrong. I'm talking about guessing at what is the same scope, or whether you can assign an array, not how to best implement some type of algorithm. – David C. Rankin Oct 04 '19 at 00:05

2 Answers2

3

what are the cases where the class C and the variable C are declared in the same scope?

Cases 1 and 4 are the same scope. Cases 2 and 3 are not the same scope.

I cannot indeed find an accurate definition in the standard for "same" in this context, but the interpretation that makes sense, and matches the results of your test is to compare the smallest enclosing scope (or rather, declarative region1) of each declaration.

Hypothesis 1: "same scope" means "same block"

While a block has a scope, they are not equivalent. There are also namespace scopes and class scopes for example.

but can't explain the case 4. Indeed, C enumerator is declared in a different block than C class but the class is still hided.

Enumeration declarations don't have a scope. The enumerator and the class are in the same scope.

Hypothesis 2: "declared in the same scope" means "have exactly the same scope"

As you say, no declaration can have exactly the same scope with another, so this interpretation would make the rule meaningless.

Hypothesis 3: "declared in the same scope" means "one of the name is declared inside the scope of the other"

This is not correct interpretation in that a nested scope can be within the scope of one declaration, but it is not the same scope as far as the rule in question is concerned.


1 In the latest standard draft, the wording has been changed to use the term "declarative region", which apparently has subtly different meaning than "scope". It doesn't change the intended meaning of the rule though.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • By reading [basic.scope] of the latest draft, I don't understand the difference between a scope and a declarative region. – Pierre Oct 04 '19 at 06:43
  • @Pierre My interpretation: The term scope is overloaded and can refer to the span from a declaration of a name until the end of the scope (the scope of a variable or type etc.), or scope can refer to the enclosing area where names can be declared (block scope, class scope etc.). Declarative region only has the latter meaning and thus reduces chance of ambiguity and misunderstanding. – eerorika Oct 04 '19 at 12:47
2

Here, by scope they mean visibility.
Two names are in the same scope if and only if somewhere they are both known at the same time (so that it becomes ambiguous/conflicting if they are the same).
By "known" I mean that you can directly access them (with exactly the same syntax if the names are the same).


Indeed, C enumerator is declared in a different block than C class but the class is still hidden.

This is wrong.
Actually the enum does not encapsulate its members in a local scope. In other words, the enum members are in the same scope that the enum itself.

For example, if I declare

enum MY_ENUM {A, B};

I can access the values either by My_ENUM::A and My_ENUM::B or simply by A and B. Moreover, implicit conversion to an int is allowed.

If you want to encapsulate the values in a scope local to MY_ENUM (and so forbid the accesses by A and B), you'll have to declare the enum as an enum class instead.

enum class MY_ENUM {A, B};

However, implicit conversion to an int will not be allowed anymore.

Fareanor
  • 5,900
  • 2
  • 11
  • 37