Template metaprogramming question

S

suman.nandan

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*> ptrList; // contains 'n' elements which are pointers to
D1 .. Dn.

I don't want to have anything like:
ptrList.push_back (new D1);
ptrList.push_back (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_back (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.
 
C

courpron

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*> ptrList; // contains 'n' elements which are pointers to
D1 .. Dn.

I don't want to have anything like:
ptrList.push_back (new D1);
ptrList.push_back (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_back (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_back (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_derived {
...
for_each_derived< Typelist::Tail,
Base,
is_derived_from< Base,
Typelist::Tail::Head >
>::run();
...
};

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


Alexandre Courpron.
 
N

Noah Roberts

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*> ptrList; // contains 'n' elements which are pointers to
D1 .. Dn.

I don't want to have anything like:
ptrList.push_back (new D1);
ptrList.push_back (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(whatever, id) \
namespace \
{ \
ControlCenter::registration reg_##id =
ControlCenter::control_center().register(whatever); \
}

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(construction, 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.
 
J

James Kanze

(e-mail address removed) wrote:
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(whatever, id) \
namespace \
{ \
ControlCenter::registration reg_##id =
ControlCenter::control_center().register(whatever); \
}

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(construction,
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.)
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.
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).
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top