How to create an alias - overlaying two class hierarchies

Discussion in 'C++' started by Matt, Oct 6, 2009.

  1. Matt

    Matt Guest

    Please help me. I really don't know a solution to this.

    I am trying to re-merge two versions of a library after a badly accepted
    code split. FLTK 1 is stable and has very few bugs. It has been
    developed in parallel with FLTK 2. FLTK 2 has (by far) a better API, but
    has become unstable due to the lack of TLC.

    My plan is to map the FLTK 2 API onto the FLTK 1 guts, creating FLTK 3
    which is source code compatible to 1 *and* 2.


    This is part of the class hierarchy:

    class Fl_Widget
    class Fl_Group : public Fl_Widget
    class Fl_Window : public Fl_Group

    and

    class fltk::Widget
    class fltk::Group : public fltk::Widget
    class fltk::Window : public fltk::Group

    Now I need a true alias that maps Fl_Widget to fltk::Widget, etc. .

    (1) A typedef does not do because a forward declaration of Fl_Widget
    would fail:

    class Fl_Widget *somePointer;
    #include <Widget.h>
    typedef fltk::Widget Fl_Widget; // error

    (2) The I tried stub classes, generating this hierarchy

    class fltk::Widget
    class Fl_Widget : public fltk::Widget
    class fltk::Group : public fltk::Widget
    class Fl_Group : public fltk::Group
    class fltk::Window : public fltk::Group
    class Fl_Window : public fltk::Window

    This fails because Fl_Group is no longer derived from Fl_Widet

    (3) This may work, but it *u*gly!

    class fltk::Widget
    class Fl_Widget : public fltk::Widget
    class fltk::Group : public Fl_Widget
    class Fl_Group : public fltk::Group
    class fltk::Window : public Fl_Group
    class Fl_Window : public fltk::Window

    (4) Using #define is out of the question... .


    Any help is greatly appreciated!


    Matthias
     
    Matt, Oct 6, 2009
    #1
    1. Advertising

  2. On 6 Ott, 18:42, Matt <> wrote:
    > Please help me. I really don't know a solution to this.
    >
    > I am trying to re-merge two versions of a library after a badly accepted
    > code split. FLTK 1 is stable and has very few bugs. It has been
    > developed in parallel with FLTK 2. FLTK 2 has (by far) a better API, but
    > has become unstable due to the lack of TLC.
    >
    > My plan is to map the FLTK 2 API onto the FLTK 1 guts, creating FLTK 3
    > which is source code compatible to 1 *and* 2.
    >
    > This is part of the class hierarchy:
    >
    > class Fl_Widget
    > class Fl_Group : public Fl_Widget
    > class Fl_Window : public Fl_Group
    >
    > and
    >
    > class fltk::Widget
    > class fltk::Group : public fltk::Widget
    > class fltk::Window : public fltk::Group
    >
    > Now I need a true alias that maps Fl_Widget to fltk::Widget, etc. .
    >
    > (1) A typedef does not do because a forward declaration of Fl_Widget
    > would fail:
    >
    > class Fl_Widget *somePointer;
    > #include <Widget.h>
    >    typedef fltk::Widget Fl_Widget; // error
    >
    > (2) The I tried stub classes, generating this hierarchy
    >
    > class fltk::Widget
    > class Fl_Widget : public fltk::Widget
    > class fltk::Group : public fltk::Widget
    > class Fl_Group : public fltk::Group
    > class fltk::Window : public fltk::Group
    > class Fl_Window : public fltk::Window
    >
    > This fails because Fl_Group is no longer derived from Fl_Widet
    >
    > (3) This may work, but it *u*gly!
    >
    > class fltk::Widget
    > class Fl_Widget : public fltk::Widget
    > class fltk::Group : public Fl_Widget
    > class Fl_Group : public fltk::Group
    > class fltk::Window : public Fl_Group
    > class Fl_Window : public fltk::Window
    >
    > (4) Using #define is out of the question... .
    >
    > Any help is greatly appreciated!


    Try posting more details - the interfaces of those classes, in
    particular.

    Also, I'm not so sure about what TLC stands for, here, top-level
    classes perhaps?

    A hierarchy could have nothing wrong in itself but its application can
    be partially or totally wrong, depending on the cases.

    Also, why did you write "this may work" for (3)? Didn't you test it?
    Depending on the cases, that could be the only way to avoid rewriting
    the interface.

    --
    Francesco S. Carta, http://fscode.altervista.org
    First time here? Read the 'Welcome' and the 'FAQ'
    Welcome: http://www.slack.net/~shiva/welcome.txt
    C++ FAQ: http://www.parashift.com/c -faq-lite
     
    Francesco S. Carta, Oct 7, 2009
    #2
    1. Advertising

  3. On 7 oct, 12:07, "Francesco S. Carta" <> wrote:
    > On 6 Ott, 18:42, Matt <> wrote:
    >
    >
    >
    > > Please help me. I really don't know a solution to this.

    >
    > > I am trying to re-merge two versions of a library after a badly accepted
    > > code split. FLTK 1 is stable and has very few bugs. It has been
    > > developed in parallel with FLTK 2. FLTK 2 has (by far) a better API, but
    > > has become unstable due to the lack of TLC.

    >
    > > My plan is to map the FLTK 2 API onto the FLTK 1 guts, creating FLTK 3
    > > which is source code compatible to 1 *and* 2.

    >
    > > This is part of the class hierarchy:

    >
    > > class Fl_Widget
    > > class Fl_Group : public Fl_Widget
    > > class Fl_Window : public Fl_Group

    >
    > > and

    >
    > > class fltk::Widget
    > > class fltk::Group : public fltk::Widget
    > > class fltk::Window : public fltk::Group

    >
    > > Now I need a true alias that maps Fl_Widget to fltk::Widget, etc. .

    >
    > > (1) A typedef does not do because a forward declaration of Fl_Widget
    > > would fail:

    >
    > > class Fl_Widget *somePointer;
    > > #include <Widget.h>
    > >    typedef fltk::Widget Fl_Widget; // error

    >
    > > (2) The I tried stub classes, generating this hierarchy

    >
    > > class fltk::Widget
    > > class Fl_Widget : public fltk::Widget
    > > class fltk::Group : public fltk::Widget
    > > class Fl_Group : public fltk::Group
    > > class fltk::Window : public fltk::Group
    > > class Fl_Window : public fltk::Window

    >
    > > This fails because Fl_Group is no longer derived from Fl_Widet

    >
    > > (3) This may work, but it *u*gly!

    >
    > > class fltk::Widget
    > > class Fl_Widget : public fltk::Widget
    > > class fltk::Group : public Fl_Widget
    > > class Fl_Group : public fltk::Group
    > > class fltk::Window : public Fl_Group
    > > class Fl_Window : public fltk::Window

    >
    > > (4) Using #define is out of the question... .

    >
    > > Any help is greatly appreciated!

    >
    > Try posting more details - the interfaces of those classes, in
    > particular.
    >
    > Also, I'm not so sure about what TLC stands for, here, top-level
    > classes perhaps?


    I think he means TCL (Tool Command Language) like tcl/tk.


    > A hierarchy could have nothing wrong in itself but its application can
    > be partially or totally wrong, depending on the cases.


    A hierarchy is a problem when you inherit an implementation, and
    looking rapidely at fltk, it is the case here.

    To the OP, your solution (2) may work if you virtually inherit:
    class fltk::Widget
    class Fl_Widget : public virtual fltk::Widget

    class fltk::Group : public virtual fltk::Widget
    class Fl_Group : public virual fltk::Group, public virtual Fl_Widget

    class fltk::Window : public virtual fltk::Group
    class Fl_Window : public fltk::Window, public virtual Fl_Group


    --
    Michael
     
    Michael Doubez, Oct 7, 2009
    #3
  4. On 7 Ott, 15:48, Michael Doubez <> wrote:
    > On 7 oct, 12:07, "Francesco S. Carta" <> wrote:
    >
    >
    >
    > > On 6 Ott, 18:42, Matt <> wrote:

    >
    > > > Please help me. I really don't know a solution to this.

    >
    > > > I am trying to re-merge two versions of a library after a badly accepted
    > > > code split. FLTK 1 is stable and has very few bugs. It has been
    > > > developed in parallel with FLTK 2. FLTK 2 has (by far) a better API, but
    > > > has become unstable due to the lack of TLC.

    >
    > > > My plan is to map the FLTK 2 API onto the FLTK 1 guts, creating FLTK 3
    > > > which is source code compatible to 1 *and* 2.

    >
    > > > This is part of the class hierarchy:

    >
    > > > class Fl_Widget
    > > > class Fl_Group : public Fl_Widget
    > > > class Fl_Window : public Fl_Group

    >
    > > > and

    >
    > > > class fltk::Widget
    > > > class fltk::Group : public fltk::Widget
    > > > class fltk::Window : public fltk::Group

    >
    > > > Now I need a true alias that maps Fl_Widget to fltk::Widget, etc. .

    >
    > > > (1) A typedef does not do because a forward declaration of Fl_Widget
    > > > would fail:

    >
    > > > class Fl_Widget *somePointer;
    > > > #include <Widget.h>
    > > >    typedef fltk::Widget Fl_Widget; // error

    >
    > > > (2) The I tried stub classes, generating this hierarchy

    >
    > > > class fltk::Widget
    > > > class Fl_Widget : public fltk::Widget
    > > > class fltk::Group : public fltk::Widget
    > > > class Fl_Group : public fltk::Group
    > > > class fltk::Window : public fltk::Group
    > > > class Fl_Window : public fltk::Window

    >
    > > > This fails because Fl_Group is no longer derived from Fl_Widet

    >
    > > > (3) This may work, but it *u*gly!

    >
    > > > class fltk::Widget
    > > > class Fl_Widget : public fltk::Widget
    > > > class fltk::Group : public Fl_Widget
    > > > class Fl_Group : public fltk::Group
    > > > class fltk::Window : public Fl_Group
    > > > class Fl_Window : public fltk::Window

    >
    > > > (4) Using #define is out of the question... .

    >
    > > > Any help is greatly appreciated!

    >
    > > Try posting more details - the interfaces of those classes, in
    > > particular.

    >
    > > Also, I'm not so sure about what TLC stands for, here, top-level
    > > classes perhaps?

    >
    > I think he means TCL (Tool Command Language) like tcl/tk.


    Looking up TLC led to several acronym expansions, but having failed to
    find one that fit, I made one up ;-)

    > > A hierarchy could have nothing wrong in itself but its application can
    > > be partially or totally wrong, depending on the cases.

    >
    > A hierarchy is a problem when you inherit an implementation,


    Amen.

    > looking rapidely at fltk, it is the case here.


    Oops, I thought the fltk thingie was something peculiar to the OP's
    project, but since you were able to find those details somewhere else,
    that had to be some third-party library.

    I didn't even think about looking it up, first time I hear about,
    thanks for pointing it out.

    Damn, seems I'm a bit behind in the "IT acculturated" trail ;-)

    --
    Francesco S. Carta, http://fscode.altervista.org
     
    Francesco S. Carta, Oct 7, 2009
    #4
  5. Matt

    Matt Guest

    Michael Doubez wrote:
    >> Also, I'm not so sure about what TLC stands for, here, top-level
    >> classes perhaps?

    >
    > I think he means TCL (Tool Command Language) like tcl/tk.


    Oh, sorry, TLC stands for "tender love and care". I meant to say that we
    did not take care of the fltk2 branch as we should have.

    >> A hierarchy could have nothing wrong in itself but its application can
    >> be partially or totally wrong, depending on the cases.

    >
    > A hierarchy is a problem when you inherit an implementation, and
    > looking rapidely at fltk, it is the case here.


    FLTK needed to be written to replace the Forms Library, a decades old
    Graphical User Interface library. It needed to be source code
    compatible. The class structure is - um - bearable, but really easy to
    understand, which makes FLTK a great beginner GUI library. It has been
    taught until recently at several universities.

    FLTK2 was the attempt to clean up the major flaws, but never took of,
    because user with existing code would not jump from V1 to V2, afraid of
    the changes required in their source code.

    Now we ended up with two libraries with 90% feature overlap, one stable
    with an ancient API, the other instable, but as many users and a better API.

    My goal is to move the stable version, FLTK 1, up and call it FLTK 3,
    but implementing both APIs, so we don't lose any more users. Then the
    additional features of FLTK 2 will be ported to FLTK 3. I am not sure if
    this a sound strategy, but I would like to give it a try and see what
    the acceptance will be.

    The problem is the aliasing of the class hierarchy which must not be
    even messier than what we have ;-)

    > To the OP, your solution (2) may work if you virtually inherit:
    > class fltk::Widget
    > class Fl_Widget : public virtual fltk::Widget
    >
    > class fltk::Group : public virtual fltk::Widget
    > class Fl_Group : public virual fltk::Group, public virtual Fl_Widget
    >
    > class fltk::Window : public virtual fltk::Group
    > class Fl_Window : public fltk::Window, public virtual Fl_Group


    Thank you, I will try that out. Does that mean that the virtually
    inherited classes must be pure virtual, too?

    Francesco: (3) I see no reason why (3) wouldn't work, but I havn't
    tested it yet. It feels a bit brute force to me and I was hoping for a
    more elegant version.

    Thanks for the hints,

    Matthias
     
    Matt, Oct 8, 2009
    #5
  6. On 8 oct, 12:45, Matt <> wrote:
    > Michael Doubez wrote:
    > >> Also, I'm not so sure about what TLC stands for, here, top-level
    > >> classes perhaps?

    >
    > > I think he means TCL (Tool Command Language) like tcl/tk.

    >
    > Oh, sorry, TLC stands for "tender love and care". I meant to say that we
    > did not take care of the fltk2 branch as we should have.


    Not caring enough to spell it full then :)

    [snip]
    >
    > > To the OP, your solution (2) may work if you virtually inherit:
    > > class fltk::Widget
    > > class Fl_Widget : public virtual fltk::Widget

    >
    > > class fltk::Group : public virtual fltk::Widget
    > > class Fl_Group : public virual fltk::Group, public virtual Fl_Widget

    >
    > > class fltk::Window : public virtual fltk::Group
    > > class Fl_Window : public fltk::Window, public virtual Fl_Group

    >
    > Thank you, I will try that out. Does that mean that the virtually
    > inherited classes must be pure virtual, too?


    Not necessarily. That depends on own your class map to one another.

    It solves the diamond shape inheritance. That way you will have the
    following hierarchy:
    Widget
    | \
    | FL_Widget
    | |
    Group |
    | \ |
    | FL_Group
    | |
    Window |
    \ |
    FL_Window


    Group and FL_Group will share the same inherited Widget instance.

    > Francesco: (3) I see no reason why (3) wouldn't work, but I havn't
    > tested it yet. It feels a bit brute force to me and I was hoping for a
    > more elegant version.


    If you don't need to bridge the two hierarchy (i.e. a FL_Widget* must
    not be a fltk::Widget*), you could just use composition and keep the
    types orthogonals:

    // FL_Widget uses internally a fltk::Widget.
    class FL_Widget
    {
    fltk::Widget* widget;

    public:
    FL_Widget():widget(new fltk::Widget())
    {}

    // interface uses widget

    protected:
    FL_Widget(fltk::Widget* w):widget(w)
    {}
    void setWidget(fltk::Widget* w)
    {
    widget=w;
    }
    };

    And in case of inheritance, you intialize according to decorated
    object:
    class FL_Group: public FL_Widget
    {
    fltk::Group* group;

    public:
    FL_Group():FL_Widget(NULL)
    ,group(new fltk::Group())
    { setWidget(group); }

    // interface uses group

    protected:
    FL_Group(fltk::Group* g):FL_Widget(g),group(g)
    {}
    void setGroup(fltk::Group* g)
    {
    group=g;
    setWidget(group);
    }
    };

    // ...

    You would also have to redefine copy constructor and operator to make
    your classes canonical; beware of destructor which must set its
    hierarchy to NULL to avoid multiple deletion.

    --
    Michael
     
    Michael Doubez, Oct 8, 2009
    #6
  7. Matt <> wrote:
    > Francesco: (3) I see no reason why (3) wouldn't work, but I havn't
    > tested it yet. It feels a bit brute force to me and I was hoping for a
    > more elegant version.


    I hope that Michael's suggestion will help you find the optimal
    solution for your issue.

    I just realized that you're one of the library's implementers, so yes,
    that's something peculiar to your project and no, from your POV that's
    not a third-party library ;-)

    I'm interested in checking it out, but I'm having hard time getting it
    - my fault, I have a weird proxyed connection. I'm going to send you
    an e-mail to the addresses I've found on your personal website, you'll
    eventually hand me some non-ftp link.

    Good luck for your projects,
    cheers,
    Francesco
    --
    Francesco S. Carta, http://fscode.altervista.org
     
    Francesco S. Carta, Oct 8, 2009
    #7
  8. Matt

    Matt Guest

    Francesco S. Carta wrote:
    > Matt <> wrote:
    > I just realized that you're one of the library's implementers, so yes,
    > that's something peculiar to your project and no, from your POV that's
    > not a third-party library ;-)


    Well, with a few hundred users, it feels like a third party library in
    that I can't change the API (much) or even the ABI between revisions. At
    least I have full access to the internals ;-)

    > I'm interested in checking it out, but I'm having hard time getting it
    > - my fault, I have a weird proxyed connection. I'm going to send you
    > an e-mail to the addresses I've found on your personal website, you'll
    > eventually hand me some non-ftp link.


    No problem. The http download is here:

    http://ftp.easysw.com/pub/fltk/

    > Good luck for your projects,


    Thanks a lot for your interest. After 12 years of being one of the core
    developers, the brain plays funny tricks with code and structures. I
    kind of feel like I personally know every line of code ;-)

    Matthias
     
    Matt, Oct 8, 2009
    #8
  9. Matt

    Matt Guest

    Michael Doubez wrote:

    > It solves the diamond shape inheritance. That way you will have the
    > following hierarchy:
    > Widget
    > | \
    > | FL_Widget
    > | |
    > Group |
    > | \ |
    > | FL_Group
    > | |
    > Window |
    > \ |
    > FL_Window
    >
    >
    > Group and FL_Group will share the same inherited Widget instance.


    Phew, yes. I read myself into the diamond problem a little (and suddenly
    remembered why I always avoided it ;-). I gave it a quick try, but
    haven't wrapped my head around it yet. I will try with a smaller project
    first.

    >> Francesco: (3) I see no reason why (3) wouldn't work, but I havn't
    >> tested it yet. It feels a bit brute force to me and I was hoping for a
    >> more elegant version.

    >
    > If you don't need to bridge the two hierarchy (i.e. a FL_Widget* must
    > not be a fltk::Widget*)


    Sorry, no, I'll have to provide that.

    I did another quick try with - hold your breath - using a simple
    "define". While this throws up different (solvable) issues, I was
    successful in compiling an FLTK 1 and almost an FLTK 2 program without
    changing a line of code. Quite unsatisfying though.

    > You would also have to redefine copy constructor and operator to make
    > your classes canonical; beware of destructor which must set its
    > hierarchy to NULL to avoid multiple deletion.


    Thanks for all the help!

    Matthias
     
    Matt, Oct 8, 2009
    #9
  10. On 8 Ott, 20:50, Matt <> wrote:
    > Francesco S. Carta wrote:
    > > Matt <> wrote:
    > > I just realized that you're one of the library's implementers, so yes,
    > > that's something peculiar to your project and no, from your POV that's
    > > not a third-party library ;-)

    >
    > Well, with a few hundred users, it feels like a third party library in
    > that I can't change the API (much) or even the ABI between revisions. At
    > least I have full access to the internals ;-)


    It's better to have such limitations, due to the consistency of the
    user-base.
    At least, this will push all the team towards injecting some more TLC
    into the next revisions - sorry, I couldn't resist making this
    malicious statement ;-)

    > > I'm interested in checking it out, but I'm having hard time getting it
    > > - my fault, I have a weird proxyed connection. I'm going to send you
    > > an e-mail to the addresses I've found on your personal website, you'll
    > > eventually hand me some non-ftp link.

    >
    > No problem. The http download is here:
    >
    > http://ftp.easysw.com/pub/fltk/


    Thanks, I was finally able to get it from the above link.

    > > Good luck for your projects,

    >
    > Thanks a lot for your interest. After 12 years of being one of the core
    > developers, the brain plays funny tricks with code and structures. I
    > kind of feel like I personally know every line of code ;-)


    You're welcome, I'm about to compile and try it out, I'll get in touch
    with your community.

    Cheers,
    Francesco
    --
    Francesco S. Carta, http://fscode.altervista.org
     
    Francesco S. Carta, Oct 9, 2009
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. S. S. Tsay
    Replies:
    1
    Views:
    390
  2. Matthias Kaeppler

    Parametric covariance in class hierarchies

    Matthias Kaeppler, Jan 22, 2006, in forum: Java
    Replies:
    6
    Views:
    404
    Roedy Green
    Jan 23, 2006
  3. Richard
    Replies:
    0
    Views:
    978
    Richard
    Oct 6, 2003
  4. grocery_stocker
    Replies:
    9
    Views:
    774
    grocery_stocker
    May 24, 2008
  5. Ulrich Eckhardt

    unit testing class hierarchies

    Ulrich Eckhardt, Oct 2, 2012, in forum: Python
    Replies:
    13
    Views:
    298
    Terry Reedy
    Oct 3, 2012
Loading...

Share This Page