开发者

Why does the number of elements in an enumeration change the visibility of a private typedef in C++?

Sorry for the not very descriptive question title. I'm not very sure how to describe this, hopefully I can make it better later if someone can explain this to me.

I was about to come on here and ask why the following example was working. It was exhibiting the behaviour I was hoping for but I wasn't sure why or whether it was standard or whether I just got lucky with the compiler. Anyway, in sorting out a minima开发者_如何学Gol working example to post here I found that it wasn't doing what I thought at all. So here it is ...

   struct Foo {
       enum BAR { A, B, C, D, E };
       private: typedef BAR BAR;
   };

   int main(int argc, char* argv[]) {
       int x = (Foo::BAR)42;
       int y = Foo::D;
  }

What seems to be happening, and what I was quite pleased about, is that, Foo takes on the enum constants after which BAR is made private. So I get no error on int y = but I get a Foo::BAR is private error at int x=. However this seems to only work with 5 or more constants in the enum, remove that E and it all compiles fine, i.e. BAR remains public.

What's at work here? Thanks.

(PS. Compiler is GCC 4.4.3)


I can verify your results about four vs. five enum elements... this looks like an obscure GCC bug.

As for "what's at work here", it's due to a technicality between different symbol namespaces in C++ (inherited from C). See this answer for more details.

If you don't want a symbol named BAR to be exposed, simply omit the tag name:

struct Foo {
    enum { A, B, C, D, E };
};

If you declare a named public enum, then no matter what you do, even if you hide the name using a typedef, outsiders can access the enum using an elaborated type specifier. Trying to hide a symbol name in this way is fruitless:

 struct Foo {
     enum BAR { A, B, C, D, E };
     private: typedef BAR BAR;
 };

 int main(int argc, char* argv[]) {
     int x = (enum Foo::BAR)42;  // works great!
     int y = Foo::D;
}

Is there any particular reason you want the constants to be public while the enum name remains private?


The typedef name should not conflict with the enum type name. Instead, the typedef name should hide the previously declared enum type name. Since the typedef name is private, it should be inaccessible from outside

Foo::BAR i; // ERROR, `Foo::BAR` is private

Still, you can refer to the hidden public enum type name by using the elaborate type specifier

enum Foo::BAR i; // OK

The enum constants themselves are, of course, public and should remain accessible in your example.

The behavior should not depend on the number of constants in the enum. If you observe the dependence you describe, it must be a bug in the compiler.


I would hate to say something like "Microsoft got it right" but I can't find anything in the standard that would advocate this kind of behavior. As far as I can tell, the typename Foo::BAR should always remain publicly accessible.

There is no deviation in this behavior from MSVC++. It always allows your code sample to compile without error. I tried everything up to 26 entries in BAR.

I would dare say this is a bug in gcc.

However I have to agree with what has already been said - I don't think this code deserves to be compiled.


Running 'g++ -c file.cpp' on MacOS X 10.6.4 with G++ 4.2.1, the code compiles without a whimper with both 4 and 5 elements in the enumeration. Adding '-Wall -pedantic' only triggers complaints about unused variables x and y.

As noted in a comment (and the question title), the number of elements in the enumeration should not affect the behaviour. To me, such varying behaviour smacks of 'bug' (in GCC).

Which is the correct behaviour is more complex; I'm loath to take a strong stance on that. On average, I favour 'Foo::BAR' was first declared public and the later private typedef should be ignored or should be an error. However, that is very far from being a definitive view on what the behaviour should be - I am very uncertain.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜