Subject: Re: [sv-ec] Protection of class types
From: Arturo Salz (Arturo.Salz@synopsys.com)
Date: Fri Mar 21 2003 - 15:05:44 PST
Kevin,
Take a look at: http://gcc.gnu.org/ml/gcc-bugs/2002-05/msg01168.html
I don't know if this has been fixed in your version of g++ (you seem to
imply that they have). If it hasn't been fixed then your test case would
still work. To verify this you'd need to generate a compiler error by
attempting to use a private class in an illegal context.
Also, I don't understand how your code can be correct. If Goo:Nested
is private, how can "Nested* foo()" be declared public? If the return type
is not visible outside Goo, how can the constructor be public? This all
seems rather suspicious.
Finally, if we do as Michael suggested then we aren't creating any backward
compatibility issues. The only difference will be that an attempt to protect
a class will currently result in a compiler error, and in an upcoming release
the error may not occur. This is an observable difference, but hardly a
backward compatibility issue.
Arturo
----- Original Message -----
From: "Kevin Cameron x3251" <Kevin.Cameron@nsc.com>
To: <sv-ec@eda.org>; <Arturo.Salz@synopsys.COM>
Sent: Friday, March 21, 2003 10:16 AM
Subject: Re: [sv-ec] Protection of class types
> From: "Arturo Salz" <Arturo.Salz@synopsys.com>
>
> Hi All,
>
> I looked at the issue of protecting types (or nested classes) in C++ and
> whether we should enable that feature in SystemVerilog-3.1.
>
> The first question is straightforward. C++ does allow nested classes and
> other type declarations to be declared private/protected/public. Unlike
> data members, which are private by default, types are public by default.
>
> After examining the issue closer, the ability to protect nested classes does
> create some undesirable complexity. Consider the following C++ class:
>
>
> ------------------------------------------------------------------------------
-- > > class Goo > { > private: > class Nested { ... }; > Nested *foo(); > }; > > If you don't include the implementation of foo in the declaration, and try to > define it out-of-body, like this: > > Nested *foo() { .... } > > Generates a compiler error since Nested is not visible at the top level. > If we write: > > Goo::Nested *foo() { .... } > > That doesn't work either since foo is private to Goo. > If we write: > > Goo::Nested *Goo::foo() { ... } > > That doesn't work!I tried this code (test.cpp) -
class Goo { private: class Nested { int bar(); public: Nested(); private: }; Nested y; public: Nested *foo(); };
main() { Goo x; }
with "g++ -c test.cpp" (v 3.2) and then did "nm -C test.o" which gives -
U __gxx_personality_v0 00000000 T main U Goo::Nested::Nested[in-charge]() 00000000 W Goo::Goo[in-charge]()
So the constructor syntax is:
Goo::Nested::Nested() {
}
and bar() is:
int Goo::Nested::bar() { }
Nested is still private to Goo.
> The problem is that class Nested is now private to Goo, thus, only members > of Goo can access the type! Thus, this function can only be defined inside > the declaration of Goo, but not anywhere else outside. > > In C++, the only way one can get around these restrictions is by changing foo > from a function to a task that takes a reference to a Nested pointer as a parameter: > > class Goo > { > private: > class Nested { ... }; > void *foo(Nested *&); > }; > > Now, foo can be declared out-of-body, thus: > > void Goo::foo(Nested *& p) { p = new Nested; } > > which, is roughly equivalent to: > Goo::Nested* Goo::foo() { return new Nested; } > > The difference is that Goo::Nested is no longer at file scope, but inside the > scope of a member of class Goo . > > ------------------------------------------------------------------------------ -- > > > It is this kind of complexity that caused the gnu folks to relax the type checking > in gcc and break with the standard by simply making all class-nested types public.
The nested classes are not necessarily public with version 3.2 of g++.
> Therefore, I recommend that class-nested types in SystemVerilog-3.1 remain > public. No decision that we make today will limit in any way our ability to add this > feature in a future release. Right now we can choose to make it an error to prefix a > type declaration with the protected or local keywords (the current proposal), or we > can allow these keywords and ignore them (as gcc has been doing). > > Arturo
While I'm not too bothered about privacy myself, I would disagree with "No decision that we make today will limit..." since making them private in future would not be backward compatible. Since G++ is probably the world's most popular C++ compiler I'd suggest doing whatever it does.
Regards, Kev.
PS: This works in g++
class Goo { private: class Nested { class Sub { public: Sub(); private: }; Sub z, *bar(); public: Nested(); private: }; Nested y; public: Nested *foo(); };
main() { Goo x; }
Goo::Nested::Nested() { bar(); }
Goo::Nested::Sub* Goo::Nested::bar() { }
Goo::Nested::Sub::Sub() { }
This archive was generated by hypermail 2b28 : Fri Mar 21 2003 - 15:06:38 PST