Re: [sv-ec] Protection of class types


Subject: Re: [sv-ec] Protection of class types
From: Kevin Cameron x3251 (Kevin.Cameron@nsc.com)
Date: Fri Mar 21 2003 - 10:16:44 PST


> 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 - 10:18:18 PST