473,395 Members | 1,678 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

a template meta problem

Hi,

I have a problem with extending some existing code. In a simplified
form, the problem looks like this:

I have four types, A, B, C, and D. Each A refers to zero, one, or more
B's and each B can be child to zero, one, or more A's. I just call that
"A is a parent of B", and "B is a child of A". The same goes for B and
C and for C and D. So A is only a parent, B and C are both parents and
children, and D is only a child.
I have many algorithms dealing with these. Most them are templates and
work on either all types, or all parent types, or all child types (and
some even only work on grandparent types). For this to work, the types
look somewhat like this:

// Beware, uncompiled code ahead!

struct tmp_nil {};

template<bool b> struct tmp_bool { enum {result=b}; };

class A;
class B;
class C;
class D;

class A {
public:
typedef tmp_bool<false> is_child;
typedef tmp_bool<true > is_parent;
typedef B child_t;
};

class B {
public:
typedef tmp_bool<true > is_child;
typedef tmp_bool<true > is_parent;
typedef A parent_t;
typedef C child_t;
};

class C {
public:
typedef tmp_bool<true > is_child;
typedef tmp_bool<true > is_parent;
typedef B parent_t;
typedef D child_t;
};

class D {
public:
typedef tmp_bool<true > is_child;
typedef tmp_bool<false> is_parent;
typedef C parent_t;
};

For example, if some algorithm needs to work on a type and recursivly
on all children and grandchildren, what the code does is this:

class some_class {
public:
//...

// this is called by users and does the recursive downstepping
template<class T> void some_algorithm(const T& obj)
{
// do some real work with 'obj'
detail::some_algorithm_(obj,typename T::is_parent()); // recurse
}

//...

private:
//...

// some_algorithm()'s implementation for parents
template<class T> void some_algorithm_(const T& obj, tmp_bool<true > /*is_parent*/)
{
for( <all children refered to by 'obj'> ) {
typename T::child_t& child = /*...*/;
some_algorithm(child);
}
}

// some_algorithm()'s implementation for childless types
template<class T> void some_algorithm_(const T& obj, tmp_bool<false> /*is_parent*/)
{
// no children, so nothing to do here
}

//...

};

This worked all very well for years. However, now my task is to introduce
some type B2, that's also a child to A (but not a parent to C):

class B2 {
public:
typedef tmp_bool<true > is_child;
typedef tmp_bool<false> is_parent;
typedef A parent_t;
};

Now, I suppose parents would need to change like this:

template<typename Head, class Tail> struct tmp_list {};

class A {
public:
typedef tmp_bool<false> is_child;
typedef tmp_bool<true > is_parent;
typedef tmp_list< B, tmp_list<C,tmp_nil> >
child_list;
};

I know how to deal with such recursive type lists. However, I only know
how to do this with _class_ templates. But it's _functon_ templates that
I have as algorithms, and they are stuck in some class (the 'some_class'
in the example above above) that provides all the necessary functionality
(retrieve objects etc.) for them. (And they also need to be members of it
because 'some_class', in reality being a friend to A, B, C, and D, is the
only thing that can actually get at the relevant information -- which is
not needed by users of A, B, C, and D.)
So given
template<class T> void some_class::some_algorithm_(const T&,tmp_bool<true>)
how can I make it call
template<class T> void some_class::some_algorithm(const T&)
for _all_ children in the child list of (the new version of) A?

As for the constraints I'm working under: The code is "mine". I am free
to change it as I need as long as the public interface doesn't change
more than ansolutely necessary. It is, however, quite a lot of code,
with many algorithms that have been maintained and fixed for years. And,
as always, the deadline is a rather tight one.
That's why I want to "implant" B2 with as little changes as necessary.
Right now it seems it's just a syntactic problem.

TIA,

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"The sarcasm is mightier than the sword."
Eric Jarvis
Dec 1 '05 #1
6 1551
Hendrik Schober wrote:
Hi,

I have a problem with extending some existing code. In a simplified
form, the problem looks like this: .... Right now it seems it's just a syntactic problem.


Any chance of creating a brief and compilable piece. I don't get
exactly how B2 plays into this.
Dec 1 '05 #2
Hendrik Schober wrote:
Hi,

I have a problem with extending some existing code. In a simplified
form, the problem looks like this:

I have four types, A, B, C, and D. Each A refers to zero, one, or more
B's and each B can be child to zero, one, or more A's. I just call that
"A is a parent of B", and "B is a child of A". The same goes for B and
C and for C and D. So A is only a parent, B and C are both parents and
children, and D is only a child.
I have many algorithms dealing with these. Most them are templates and
work on either all types, or all parent types, or all child types (and
some even only work on grandparent types). For this to work, the types
look somewhat like this:

// Beware, uncompiled code ahead!

struct tmp_nil {};

template<bool b> struct tmp_bool { enum {result=b}; };

class A;
class B;
class C;
class D;

class A {
public:
typedef tmp_bool<false> is_child;
typedef tmp_bool<true > is_parent;
typedef B child_t;
};

class B {
public:
typedef tmp_bool<true > is_child;
typedef tmp_bool<true > is_parent;
typedef A parent_t;
typedef C child_t;
};

class C {
public:
typedef tmp_bool<true > is_child;
typedef tmp_bool<true > is_parent;
typedef B parent_t;
typedef D child_t;
};

class D {
public:
typedef tmp_bool<true > is_child;
typedef tmp_bool<false> is_parent;
typedef C parent_t;
};

For example, if some algorithm needs to work on a type and recursivly
on all children and grandchildren, what the code does is this:

class some_class {
public:
//...

// this is called by users and does the recursive downstepping
template<class T> void some_algorithm(const T& obj)
{
// do some real work with 'obj'
detail::some_algorithm_(obj,typename T::is_parent()); // recurse
No namespace/class called detail is given. I'm assuming that you meant
to call the private template member functions given below and not a
function that is not shown.
}

//...

private:
//...

// some_algorithm()'s implementation for parents
template<class T> void some_algorithm_(const T& obj, tmp_bool<true > /*is_parent*/)
{
for( <all children refered to by 'obj'> ) {
typename T::child_t& child = /*...*/;
some_algorithm(child);
}
}

// some_algorithm()'s implementation for childless types
template<class T> void some_algorithm_(const T& obj, tmp_bool<false> /*is_parent*/)
{
// no children, so nothing to do here
}

//...

};

This worked all very well for years. However, now my task is to introduce
some type B2, that's also a child to A (but not a parent to C):

class B2 {
public:
typedef tmp_bool<true > is_child;
typedef tmp_bool<false> is_parent;
typedef A parent_t;
};

Now, I suppose parents would need to change like this:

template<typename Head, class Tail> struct tmp_list {};

class A {
public:
typedef tmp_bool<false> is_child;
typedef tmp_bool<true > is_parent;
typedef tmp_list< B, tmp_list<C,tmp_nil> >
child_list;
I think you meant B2 not C in this typedef.
};

I know how to deal with such recursive type lists. However, I only know
how to do this with _class_ templates. But it's _functon_ templates that
I have as algorithms, and they are stuck in some class (the 'some_class'
in the example above above) that provides all the necessary functionality
(retrieve objects etc.) for them. (And they also need to be members of it
because 'some_class', in reality being a friend to A, B, C, and D, is the
only thing that can actually get at the relevant information -- which is
not needed by users of A, B, C, and D.)
So given
template<class T> void some_class::some_algorithm_(const T&,tmp_bool<true>)
how can I make it call
template<class T> void some_class::some_algorithm(const T&)
for _all_ children in the child list of (the new version of) A?

[snip]

Before we can answer that, I think we need to see how you plan to
reference children of A. You have given us the typedef for the child
list, but how do you declare a child (or a pointer or reference to a
child) which is a member of A and a type in that list?

Cheers! --M

Dec 1 '05 #3
Gianni Mariani <gi*******@mariani.ws> wrote:
Hendrik Schober wrote:
Hi,

I have a problem with extending some existing code. In a simplified
form, the problem looks like this: ...
Right now it seems it's just a syntactic problem.


Any chance of creating a brief and compilable piece.


My problem is that I have no idea what a compilable
piece would look like.
I don't get
exactly how B2 plays into this.

It's a sibling to B, except that it isn't a parent to C.

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"The sarcasm is mightier than the sword."
Eric Jarvis
Dec 1 '05 #4
mlimber <ml*****@gmail.com> wrote:
[...]
For example, if some algorithm needs to work on a type and recursivly
on all children and grandchildren, what the code does is this:

class some_class {
public:
//...

// this is called by users and does the recursive downstepping
template<class T> void some_algorithm(const T& obj)
{
// do some real work with 'obj'
detail::some_algorithm_(obj,typename T::is_parent()); // recurse
No namespace/class called detail is given. I'm assuming that you meant
to call the private template member functions given below and not a
function that is not shown.


Yep. Sorry for that. I first made this example using
free functions. Only later I realized that the fact
that they are members might be of some (syntactic)
significance. So I changed the example and forgot
this.
[...]
Now, I suppose parents would need to change like this:

template<typename Head, class Tail> struct tmp_list {};

class A {
public:
typedef tmp_bool<false> is_child;
typedef tmp_bool<true > is_parent;
typedef tmp_list< B, tmp_list<C,tmp_nil> >
child_list;
I think you meant B2 not C in this typedef.


Um, yeah. Sorry. :(
[...]

Before we can answer that, I think we need to see how you plan to
reference children of A. You have given us the typedef for the child
list, but how do you declare a child (or a pointer or reference to a
child) which is a member of A and a type in that list?
I don't see how this is relevant.
Maybe my OP was a bit misleading in its terminology.
<sigh>

I'll try to clarify:
Instances of A can be parents to instances of B. This
is a /run-time/ relationship. It could be achieved by
simple pointers. (In the real code, it is achieved by
each A having a list of IDs that (exclusivly) refer to
Bs. 'some_class' has some functions that hand out
references to the real objects when given the right
IDs.)
However, the important part is: Which A refers to
which B is a /run-time/ thing. That instances of A
always refer to instances of B is a /compile-time/
thing.

I haven't shown the actual run-time referencing stuff,
because I think it isn't relevant. Just assume that A
has some member templates that, given B as a template
arg, let you iterate over a list of instances of B.
The compile-time stuff needs to find out that instances
of A always refer to instances of B as children (and
that thus B should be passed to those member templates
of A).
This works for several years.
I now need to extend that compile-time mechanism so that
it finds out that instances of A refer to instances of B
/and/ instances of B2 as children and then iterates over
both child lists.
(And I need to have the very same algorithms working
with B-C and C-D relationships as well, where there's
only one child.)

What I am having problems with is that I need to change
the mechanics which, at compile time, used to find out
/if/ there's a (one) child type and, if so, iterated,
at run-time, over /the/ (one) child list into some
mechanics that, at compile-time, find out /how many/
child types there are and generates the code to, at
run-time, iterate over /all/ of those child lists.

I hope that's clearer now.
Cheers! --M

Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"The sarcasm is mightier than the sword."
Eric Jarvis
Dec 1 '05 #5
Hendrik Schober wrote:
[snip]
I now need to extend that compile-time mechanism so that
it finds out that instances of A refer to instances of B
/and/ instances of B2 as children and then iterates over
both child lists.
(And I need to have the very same algorithms working
with B-C and C-D relationships as well, where there's
only one child.)

What I am having problems with is that I need to change
the mechanics which, at compile time, used to find out
/if/ there's a (one) child type and, if so, iterated,
at run-time, over /the/ (one) child list into some
mechanics that, at compile-time, find out /how many/
child types there are and generates the code to, at
run-time, iterate over /all/ of those child lists.

I hope that's clearer now.


Ok. You said previously that you know how to recurse the typelists
already. Could you change each parent object (A, B, and C) to have a
typelist of children rather than a simple child type, and then change
your functions to iterate over those lists? That way there is no
operational difference between having one child type and multiple, but
only A would actually have multiple types (viz. B and B2) in its list.
The remaining challenge would be to acquire the proper child object,
but that could be accomplished by adding to each parent class a
template member function that is specialized for each of its children,
e.g.,

class A
{
// ...
template <class Child> Child GetChild();
template <> B& GetChild<B >() { /* return a B */ }
template <> B2& GetChild<B2>() { /* return a B2 */ }
};

Then your algorithm would use obj.Get<ChildType>() to retrieve the
child for processing. ChildType would be determined by the current
"iteration" of the child typelist.

Cheers! --M

Dec 1 '05 #6
mlimber <ml*****@gmail.com> wrote:
[...]
Ok. You said previously that you know how to recurse the typelists
already. Could you change each parent object (A, B, and C) to have a
typelist of children rather than a simple child type, and then change
your functions to iterate over those lists? That way there is no
operational difference between having one child type and multiple, but
only A would actually have multiple types (viz. B and B2) in its list.
That's what I was planning. However, I didn't see a
way to iterate over typelists except by using class
templates. But I just realized I could have a function
recursivly calling itself with the tail of the list.
If the function has an overload of the tmp_nil type,
this would stop the recursion.
The remaining challenge would be to acquire the proper child object,
That's no problem. I had solved that before. :)
I just didn't know how to process TMP lists using
function templates...

Thanks for your help! I like to have things set up in
my head a few days before I start implementing them.
[...]
Cheers! --M


Schobi

--
Sp******@gmx.de is never read
I'm Schobi at suespammers dot org

"The sarcasm is mightier than the sword."
Eric Jarvis
Dec 2 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Ingo Nolden | last post by:
Hi, I want to write a template class that holds another class that uses the same template. This recursion should stop after a predefined number. I think it's either impossible or easy, but I...
8
by: Tjerk Wolterink | last post by:
I have xml inpput like this: <meta:empty/> And xsl like this: <xsl:template match="meta:empty">A</xsl:template> <xsl:template match="//meta:*">B</xsl:template>
8
by: fernandezr | last post by:
I would like to use a user control as a template inside a repeater. Some of the fields in the control should be hidden depending on whether or not there is data. I'm still a ASP .Net newbie so the...
8
by: Jon Rea | last post by:
http://osl.iu.edu/~tveldhui/papers/Template-Metaprograms/meta-art.html Can anyone shed some light on the need for stuff like this when using any of the most modern compilers? If i have a...
6
by: bogus1one | last post by:
Hi All Given the following: // NamespaceTemplate.cpp : Defines the entry point for the console application. // #include "stdafx.h"
7
by: Kevin | last post by:
I'm creating a template to support state machines. In doing so, I need to pass an enumeration for the number of transitions and a non type parameter for the range of the enum (to allow me to...
3
by: stdlib99 | last post by:
Hi, I have a simple question regarding templates and meta programming. I am going to try and work my way through the C++ Template Metaprogramming, a book by David Abrahams and Aleksey...
4
by: z55177 | last post by:
My domain: http://www.esthevision.cz/ This is the cause of my problem. The template is supposed to look somewhat like this: PINK STRIPE http://themebot.com/website-templates/ht... I created an...
2
by: Clyde | last post by:
Hi, what i'm trying to do is: /////////////// Code Start template <class TType, int* p = 0> class Template { public:
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.