Topic: recursive nested class .


Author: "Gene Bushuyev" <gbush@synopsys.com>
Date: 1999/08/16
Raw View
David R Tribble <david@tribble.com> wrote in message
news:37B48C18.282C3A93@tribble.com...
> Why not avoid void pointers altogether and use a common base class for
> the nested derived class types?:
>
>     struct NestedBase
>     { };
>
[snip]

Once you introduced a NestedBase I don't see the reason why not to make it
fully functional, performing the same functions as one of the nested
classes. By doing so, you make the whole thing easier to understand and you
don't need to inherit from NestedBase at all, unless you have something else
in mind than the original question. Nor you will need any dynamic_casts when
using "NestedBase *     recurs"
I think the desire to keep recursive nested classes by all means in the
absence of direct language support doesn't have much substance to it.

Gene Bushuyev.




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "gbush" <gbush@my-deja.com>
Date: 1999/08/16
Raw View
Siemel B. Naran <sbnaran@uiuc.edu> wrote in message
news:slrn7r5t3v.kn9.sbnaran@localhost.localdomain...
[snip]
> No, this is not the only way.  In the past I've used a void* pointer
> every now and then.  For example:

Using void* is an evil thing and often is an indication that you are doing
something C++ doesn't approve. As you correctly noticed compiler will
torture you with the cast requirements every now and then. In any
non-trivial program the possibility of error when using void* casts is
prohibitively high.
[snip]
>
>    // C1.hh
>    class C1 { class I; auto_ptr<I> i; public: class Nested { }; C1();
~C1(); };
>
>    // C2.hh
>    class C2 { class I; auto_ptr<I> i; public: class Nested { }; C2();
~C2(); };
>
>    // C1.cc
>    #include "C1.hh"
>    #include "C2.hh"
>    struct C1::I { C2::Nested thing; I() { } }
>    C1::C1() : i(new I()) { }
>    C1::~C1() { }
>
I fail to see how this solves the problem, even if you add missing ";" and
resolve class/struct discrepancy. The fact that class I is incomplete in
C1/C2 prevent from any reasonable use of it, other than in name only. This
actually true with void* or any other pointers to incomplete types. But even
if you solve that problem, you are still left with evil casts.

Gene Bushuyev




[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: fvali <fvali@kumc.edu>
Date: 1999/08/16
Raw View
I was informed that something went wrong with my initial post, so I;'m
posting it again.  I hope it doesn't get repeated.

Christian Templier STNA 7SO p5747 K224 wrote:
>
> hello
>
> i write this text because i have a probleme with recursive nested class .
>
> the probleme is when there is a recusion beetween two nested class who
> are enclosing in different  class and use in their own enclosing class .

<snip>

If you are willing to use templates, and your compiler compiles the
following without errors then this simple hack might work.
I must add that I've never had to use this in production code, so I
can't vouch for the integrity of its design unless it is analyzed more
thoroughly or it is actually used and its advantages and disadvantages
are weighed.


struct OuterB;

struct OuterA
{
private:
  template< typename OTY_ >
    struct InnerT
  {
    typedef typename OTY_::Inner OtherInner;

    std::auto_ptr<OtherInner> m_in;

    InnerT() : m_in( new OtherInner )
    {
    }

    ~InnerT()
    {
      OtherInner b;  // e.g.

    }
  };

public:

  typedef InnerT<OuterB> Inner;

};

struct OuterB
{
  struct Inner;
};

struct OuterB::Inner
{

  std::auto_ptr<OuterA::Inner> m_in;


  Inner() : m_in( 0 )
  {  }

  void f()
  {
      OuterA::Inner i;
  }
};

This compiles without errors in gcc-2.95 mingw32 as it should according
to the standard.

hope that helps.

Can you expand on your situation though - I'm curious as to whether it
really is good design (pending input by the design gurus of course).

-fais
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: David R Tribble <david@tribble.com>
Date: 1999/08/14
Raw View
"Siemel B. Naran" wrote:
>
> On 12 Aug 1999 15:19:49 GMT, Gene Bushuyev <gbush@synopsys.com> wrote:
>
>> Unfortunately, current C++ standard doesn't allow forward
>> declaration of the nested class outside of the enclosing class.
>> Therefore, the only way of solving this problem is to break
>> encapsulation and expose at least partially one of the nested
>> classes. Using your example,
>
> No, this is not the only way.  In the past I've used a void* pointer
> every now and then.  For example:
>
>    // C1.hh
>    class C1 { void * thing; public: class Nested { }; C1(); ~C1(); };
>
>    // C2.hh
>    class C2 { void * thing; public: class Nested { }; C2(); ~C2(); }
>
>    // C1.cc
>    #include "C1.hh"
>    #include "C2.hh"
>    C1::C1() { d_thing=new C2::Nested(); }
>    C1::~C1() { delete static_cast<void *>(d_thing); }
>
> This is perfectly safe, but having to write all these static_casts is
> tedious.  Eventually I learned that we can use undefined structs
> instead.

Why not avoid void pointers altogether and use a common base class for
the nested derived class types?:

    struct NestedBase
    { };

    class First
    {
    public:
        class Nested: public NestedBase
        {
            NestedBase *     recurs;
                                 // polymorphic Second::Nested
            ...
        };
    };

    class Second
    {
    public:
        class Nested: public NestedBase
        {
            First::Nested *  recurs;
            ...
        };
    };

You still have to cast the 'First::Nested::recurs' pointer to type
'Second::Nested *', but this is safer than casting it from a void
pointer.

-- David R. Tribble, david@tribble.com --
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Gene Bushuyev" <gbush@synopsys.com>
Date: 1999/08/12
Raw View
Unfortunately, current C++ standard doesn't allow forward declaration of the
nested class outside of the enclosing class. Therefore, the only way of
solving this problem is to break encapsulation and expose at least partially
one of the nested classes. Using your example,

class FIRST ;
class SECOND ;
// introduce a new class in the outer namespace
class SECOND_NESTED;

class FIRST
{
  public:
  class NESTED
  { SECOND_NESTED *recursive ;} ;
  private:
  NESTED value ;
} ;

class SECOND_NESTED
{ public: FIRST::NESTED *recursive ;};

class SECOND
{
  public:
  typedef SECOND_NESTED NESTED;
  private:
  NESTED value ;
} ;

Gene Bushuyev.

Christian Templier STNA 7SO p5747 K224 wrote in message <199908111550.RAA06843@blueberry.stna.dgac.fr>...
>
>hello
>
>i write this text because i have a probleme with recursive nested class .
>
>the probleme is when there is a recusion beetween two nested class who
>are enclosing in different  class and use in their own enclosing class .
>





[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/12
Raw View
On 11 Aug 1999 18:33:31 GMT, Christian Templier

>class FIRST ;
>class SECOND ;
>class FIRST::NESTED  ;
>class SECOND ::NESTED ;
>
>class FIRST
>{
>class NESTED
>    {SECOND::NESTED *recursive ;
>    } ;
>NESTED value ;
>} ;

What if class SECOND::NESTED is private?
Then declararing the pointer "SECOND::NESTED *recursive" is an error.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/08/13
Raw View
On 12 Aug 1999 15:19:49 GMT, Gene Bushuyev <gbush@synopsys.com> wrote:

>Unfortunately, current C++ standard doesn't allow forward declaration of the
>nested class outside of the enclosing class. Therefore, the only way of
>solving this problem is to break encapsulation and expose at least partially
>one of the nested classes. Using your example,

No, this is not the only way.  In the past I've used a void* pointer
every now and then.  For example:

   // C1.hh
   class C1 { void * thing; public: class Nested { }; C1(); ~C1(); };

   // C2.hh
   class C2 { void * thing; public: class Nested { }; C2(); ~C2(); }

   // C1.cc
   #include "C1.hh"
   #include "C2.hh"
   C1::C1() { d_thing=new C2::Nested(); }
   C1::~C1() { delete static_cast<void *>(d_thing); }

This is perfectly safe, but having to write all these static_casts is
tedious.  Eventually I learned that we can use undefined structs
instead.  It feels a little cleaner:

   // C1.hh
   class C1 { class I; auto_ptr<I> i; public: class Nested { }; C1(); ~C1(); };

   // C2.hh
   class C2 { class I; auto_ptr<I> i; public: class Nested { }; C2(); ~C2(); };

   // C1.cc
   #include "C1.hh"
   #include "C2.hh"
   struct C1::I { C2::Nested thing; I() { } }
   C1::C1() : i(new I()) { }
   C1::~C1() { }




Finally, I can't resist mention this style issue.  If it is necessary to
forward declare nested classes, then perhaps we need to use nested
namespaces?  Certainly not always, but at least consider the question for
your application.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christian Templier STNA 7SO p5747 K224 <templier@stna.dgac.fr>
Date: 1999/08/11
Raw View
hello

i write this text because i have a probleme with recursive nested class .

the probleme is when there is a recusion beetween two nested class who
are enclosing in different  class and use in their own enclosing class .

example :

class FIRST ;

class SECOND ;

class FIRST
{
class NESTED
    {SECOND::NESTED *recursive ;
    } ;
NESTED value ;
} ;

class SECOND
{
class NESTED
    {FIRST::NESTED *recursive ;
    } ;
NESTED value ;
} ;


in this example we can not use external NESTED class because
for value NESTED must be define with the contain .

class FIRST
{
class NESTED;
NESTED value ;
} ;

class SECOND
{
class NESTED;
NESTED value ;
} ;

class SECOND::NESTED
    {FIRST::NESTED *recursive ;
    } ;

class FIRST::NESTED
    {SECOND::NESTED *recursive ;
    } ;

i propose to add to C++ normalisation this syntaxe very easy to implement :


class FIRST ;

class SECOND ;

class FIRST::NESTED  ;

class SECOND ::NESTED ;

class FIRST
{
class NESTED
    {SECOND::NESTED *recursive ;
    } ;
NESTED value ;
} ;

class SECOND
{
class NESTED
    {FIRST::NESTED *recursive ;
    } ;
NESTED value ;
} ;

the syntaxe class FIRST::NESTED  ; allow  to declare a nested class without define it .
then we can have recursive type .

namespace can not resolve the probleme if we have NESTED class on n level with n> 2 .

could you tell me what do you thing about  ?


 ____________________________________________________________________________
|                |             |                                             |
|   ___    ___   | TEMPLIER    |                                             |
|  /__ \  / __\  |  christian  | Service Technique de la Navigation Aerienne |
|   __\ \/ /     |_____________|_____________________________________________|
|  / __   |   _  |             |                                             |
|  \ \_\   \_//  | Toulouse    | web http://www.stna.dgac.fr/~templier       |
|   \___/\___/   |      France | E_mail : templier@stna.dgac.fr              |
|                |             | tel    : 05.62.14.57.47                     |
 ----------------------------------------------------------------------------
[ Oz web page  http://www.ps.uni-sb.de/oz/   ]
[ list administration oz-users-request@ps.uni-sb.de ]



[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/08/12
Raw View
Christian Templier STNA 7SO p5747 K224 wrote:

> the probleme is when there is a recusion beetween two nested class who
> are enclosing in different  class and use in their own enclosing class .

> class FIRST ;
>
> class SECOND ;
>
> class FIRST
> {
> class NESTED
>     {SECOND::NESTED *recursive ;
>     } ;
> NESTED value ;
> } ;
>
> class SECOND
> {
> class NESTED
>     {FIRST::NESTED *recursive ;
>     } ;
> NESTED value ;
> } ;

> could you tell me what do you thing about  ?

Hello Christian Templier STNA 7SO p5747 K224

Since nested classes are mostly syntaxic suggar with access
control, you can easilly rewrite such code (giving up access
control):

class First_Nested;

class Second_Nested {
    First_Nested* p;
};

class First_Nested {
    Second_Nested* p;
};

class First {
    typedef First_Nested Nested;
    Nested x;
};

class Second {
    typedef Second_Nested Nested;
    Nested x;
};

--

Valentin Bonnard
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]