Template metaprogramming question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • suman.nandan@gmail.com

    #1

    Template metaprogramming question

    Hi C++ Experts !
    I have a little weird requirement.

    I have a base class, say B and lots of classes D1 .. Dn publicly
    derived from it. Over the course of development the number of derived
    classes may increase.
    I want that before the execution of one of my particular code, I
    should have a list of pointers to all the derived classes, say
    std::list<B*ptr List; // contains 'n' elements which are pointers to
    D1 .. Dn.

    I don't want to have anything like:
    ptrList.push_ba ck (new D1);
    ptrList.push_ba ck (new D2);
    ...

    Also I don't want to instantiate any static variable of D1 .. Dn, so
    that inside the constructor I may register the 'this' pointer.

    All I want is the developer should just write the definition of
    derived classes, possibly with some constraints and should not bother
    about anything else.

    Recently I read about 'TypeLists' in Modern C++ design. I was
    wondering if I can use it here.

    Inside the constructor of the derived classes, I may populate its type
    in a 'TypeList'. The 'TypeList' will be full with 'n' elements at the
    compile time itself.
    Now if I only can do

    for each type T in 'TypeList' {
    // make sure that type T is derived class of B
    // may be through
    // assert (dynamic_cast<B *>(T));

    ptrList.push_ba ck (new T);
    }
    my problem will be solved.

    Do you guys see any problem with this approach?

    Any discussion on this will be appreciated.

    Thanks in advance !!
    Suman Nandan.
  • Victor Bazarov

    #2
    Re: Template metaprogramming question

    suman.nandan@gm ail.com wrote:
    Hi C++ Experts !
    I have a little weird requirement.
    >
    I have a base class, say B and lots of classes D1 .. Dn publicly
    derived from it. Over the course of development the number of derived
    classes may increase.
    I want that before the execution of one of my particular code, I
    should have a list of pointers to all the derived classes, say
    std::list<B*ptr List; // contains 'n' elements which are pointers to
    D1 .. Dn.
    There are no "pointers to classes", only pointers to objects, and you
    understand that, right?

    What purpose would such list serve?
    I don't want to have anything like:
    ptrList.push_ba ck (new D1);
    ptrList.push_ba ck (new D2);
    ..
    To have anything like that *where*? What would it do (for you)?
    >
    Also I don't want to instantiate any static variable of D1 .. Dn, so
    that inside the constructor I may register the 'this' pointer.
    Inside which constructor? Inside every derived class constructor?
    All I want is the developer should just write the definition of
    derived classes, possibly with some constraints and should not bother
    about anything else.
    The simplest solution I can think of to "register" your derived class
    with the base class is a special "registrar" object which, when
    instantiated passes some data (like its own address or the address of
    the containing object) to the base class' registering function. The
    details of the process are for you to determine, but this should give
    you an idea.
    >
    Recently I read about 'TypeLists' in Modern C++ design. I was
    wondering if I can use it here.
    Mmm... I don't think this is something you would be able to use here.
    Inside the constructor of the derived classes, I may populate its type
    in a 'TypeList'. The 'TypeList' will be full with 'n' elements at the
    compile time itself.
    Now if I only can do
    >
    for each type T in 'TypeList' {
    // make sure that type T is derived class of B
    // may be through
    // assert (dynamic_cast<B *>(T));
    >
    ptrList.push_ba ck (new T);
    }
    my problem will be solved.
    What problem is that?
    Do you guys see any problem with this approach?
    Well, yes. 'Typelist' (or anything like this) is compile-time
    information and most likely not going to suit you. I shouldn't have to
    update your base class information if I add a derived class in my own
    module.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask

    Comment

    • courpron@gmail.com

      #3
      Re: Template metaprogramming question

      On 15 juil, 14:59, suman.nan...@gm ail.com wrote:
      Hi C++ Experts !
      I have a little weird requirement.
      >
      I have a base class, say B and lots of classes D1 .. Dn publicly
      derived from it. Over the course of development the number of derived
      classes may increase.
      I want that before the execution of one of my particular code, I
      should have a list of pointers to all the derived classes, say
      std::list<B*ptr List; // contains 'n' elements which are pointers to
      D1 .. Dn.
      >
      I don't want to have anything like:
      ptrList.push_ba ck (new D1);
      ptrList.push_ba ck (new D2);
      ..
      >
      Also I don't want to instantiate any static variable of D1 .. Dn, so
      that inside the constructor I may register the 'this' pointer.
      >
      All I want is the developer should just write the definition of
      derived classes, possibly with some constraints and should not bother
      about anything else.
      >
      Recently I read about 'TypeLists' in Modern C++ design. I was
      wondering if I can use it here.
      >
      Inside the constructor of the derived classes, I may populate its type
      in a 'TypeList'. The 'TypeList' will be full with 'n' elements at the
      compile time itself.
      Now if I only can do
      >
         for each type T in 'TypeList'  {
            // make sure that type T is derived class of B
            // may be through
            // assert (dynamic_cast<B *>(T));
      >
             ptrList.push_ba ck (new T);
         }
      my problem will be solved.
      >
      Do you guys see any problem with this approach?
      >
      Any discussion on this will be appreciated.
      >
      Thanks in advance !!
      Suman Nandan.

      If you want to go with this design, here are some very quick
      guidelines (sorry I'm in a hurry).

      You need :

      1) a for_each structure that will iterate through the typelist :
      something like (simplified and untested example) :

      template < class Typelist >
      struct for_each {
      static void run ()
      {
      ptrList.push_ba ck (new Typelist::Head) ;
      for_each< Typelist::Tail >::run();
      }
      };


      template < >
      struct for_each< NullType {
      static void run () {}
      };


      2) the is_derived_from idiom :

      template< class Base, class Derived >
      struct IsDerivedFrom{
      typedef char Yes;
      struct No { char x[2]; };

      static Yes Test( Base* );
      static No Test( ... );

      enum {check = sizeof( Test( static_cast< Derived* >(0) ) )
      == sizeof( Yes )
      };
      };


      3) use the is_derived_from idiom to enhance the for_each structure.

      template < class Typelist, class Base, bool IsDerived >
      struct for_each_derive d {
      ...
      for_each_derive d< Typelist::Tail,
      Base,
      is_derived_from < Base,
      Typelist::Tail: :Head >
      >::run();
      ...
      };

      // template specializations on IsDerived = true or false ...


      Alexandre Courpron.

      Comment

      • Noah Roberts

        #4
        Re: Template metaprogramming question

        suman.nandan@gm ail.com wrote:
        Hi C++ Experts !
        I have a little weird requirement.
        >
        I have a base class, say B and lots of classes D1 .. Dn publicly
        derived from it. Over the course of development the number of derived
        classes may increase.
        I want that before the execution of one of my particular code, I
        should have a list of pointers to all the derived classes, say
        std::list<B*ptr List; // contains 'n' elements which are pointers to
        D1 .. Dn.
        >
        I don't want to have anything like:
        ptrList.push_ba ck (new D1);
        ptrList.push_ba ck (new D2);
        ..
        As Bazarov stated, use a registration object.


        // id argument is unnecissary for registration, but it does make it
        possible to register more than
        // one control in a .cpp file while still making some sense.
        #define REGISTER(whatev er, id) \
        namespace \
        { \
        ControlCenter:: registration reg_##id =
        ControlCenter:: control_center( ).register(what ever); \
        }

        In my case, id is an integral defined in resource.h as a Win32 control
        object and this implements a state/command pattern tool system.

        ControlCenter:: registration can easily simply be a bool and is normally
        ignored. You'll be able to access it if necessary, keeping scoping
        issues in mind, though as the variable name is quite predictable.

        Developers write a class and then put "REGISTER(const ruction, id)" in
        the cpp file. You could easily simply use the ID instead, or something
        along those lines, so that instantiation is not necessary (in my case it
        is). There's no need to even have a header for these objects at
        all...the class interface and implementation can be in the CPP file and
        never exposed to anyone at all.
        >
        Also I don't want to instantiate any static variable of D1 .. Dn, so
        that inside the constructor I may register the 'this' pointer.
        I don't know what you mean here so I can't say if it'll solve your problem.
        >
        All I want is the developer should just write the definition of
        derived classes, possibly with some constraints and should not bother
        about anything else.
        What you want is not possible, at least no way I can think of. It's not
        really a template metaprogramming problem either. There might be
        something you could do with a traits function explicit instantiation,
        one that the REGISTER macro would create, but I don't understand what
        your problem is well enough to say.

        Comment

        • James Kanze

          #5
          Re: Template metaprogramming question

          On Jul 15, 11:03 pm, Noah Roberts <u...@example.n etwrote:
          suman.nan...@gm ail.com wrote:
          I have a base class, say B and lots of classes D1 .. Dn
          publicly derived from it. Over the course of development the
          number of derived classes may increase.
          I want that before the execution of one of my particular
          code, I should have a list of pointers to all the derived
          classes, say std::list<B*ptr List; // contains 'n' elements
          which are pointers to D1 .. Dn.
          I don't want to have anything like:
          ptrList.push_ba ck (new D1);
          ptrList.push_ba ck (new D2);
          ..
          As Bazarov stated, use a registration object.
          // id argument is unnecissary for registration, but it does make it
          possible to register more than
          // one control in a .cpp file while still making some sense.
          #define REGISTER(whatev er, id) \
          namespace \
          { \
          ControlCenter:: registration reg_##id =
          ControlCenter:: control_center( ).register(what ever); \
          }
          Just an idea, but if you use __LINE__ instead of id, and you
          won't need the extra argument.
          In my case, id is an integral defined in resource.h as a Win32
          control object and this implements a state/command pattern
          tool system.
          ControlCenter:: registration can easily simply be a bool and is
          normally ignored. You'll be able to access it if necessary,
          keeping scoping issues in mind, though as the variable name is
          quite predictable.
          Developers write a class and then put "REGISTER(const ruction,
          id)" in the cpp file. You could easily simply use the ID
          instead, or something along those lines, so that instantiation
          is not necessary (in my case it is). There's no need to even
          have a header for these objects at all...the class interface
          and implementation can be in the CPP file and never exposed to
          anyone at all.
          I'm not sure I understand. You need a header for the class
          ControlCenter (or whatever it would be called), and the register
          macro, since the registration will take place in many different
          files. (Personally, I've never bothered with the macro. I just
          define a member class of ControlCenter, and require a static
          instance of that, e.g.:
          ControlCenter:: Registerer someId( whatever ) ;
          It's up to the user to worry about someId, and do whatever he
          feels necessary to avoid name clashes, but the effort has never
          seemed sufficient to justify a macro. IMHO.)
          Also I don't want to instantiate any static variable of D1
          .. Dn, so that inside the constructor I may register the
          'this' pointer.
          I don't know what you mean here so I can't say if it'll solve
          your problem.
          He's saying basically that he wants something, but refuses to
          use any of the known techniques to achieve it.
          All I want is the developer should just write the definition
          of derived classes, possibly with some constraints and
          should not bother about anything else.
          What you want is not possible, at least no way I can think of.
          It's not really a template metaprogramming problem either.
          There might be something you could do with a traits function
          explicit instantiation, one that the REGISTER macro would
          create, but I don't understand what your problem is well
          enough to say.
          It seems rather obvious that template metaprogramming couldn't
          be a solution in itself, since templates are fully resolved at
          compile time, and as I understand it, the system must be open to
          classes which are separately compiled. You can't say, I want
          this resolved at compile time, but the information won't be
          available until link time (or maybe runtime, if dynamic linking
          is being used).

          Note that if static linking is being used, it should be possible
          to insert a small script which generates a source with all of
          the information, in a statically initialized table (with
          std::find being used for lookup). This can have certain
          advantages in some cases (and major disadvantages in others).

          --
          James Kanze (GABI Software) email:james.kan ze@gmail.com
          Conseils en informatique orientée objet/
          Beratung in objektorientier ter Datenverarbeitu ng
          9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

          Comment

          Working...