Automatic template generation via. recursive preprocessor ...

1436 views
Skip to first unread message

Chris Thomasson

unread,
Jun 19, 2006, 7:26:01 AM6/19/06
to

Here is a "simple" method for using the preprocessor to generate code via.
recursion. I have a very quick and dirty example of how you can use the
recursion facilities to automatically generate partial or explicit template
specializations for "mechanical looking code"; such as "typelist creation
templates", this is the example I used in my test code. Anyway, what do you
think of my experimental recursion implementation?

Can you compile it?


Any comments/tips/tricks are welcome... I just started messing around with
this preprocessor meta-programming thing, I may need major help!

;)

Here is a very quick example application:

http://appcore.home.comcast.net/appcore/src/meta-pp-recursion.cpp


P.S. This example supports a max-recursion depth of 5. Of course, the limit
could be hundreds of times larger; whoa, what a big file!


If you want to set a deeper recursion depth you will have to add-on to the
VZMETAPP_ENCODING and VZPPMETA_RECURSE family of macros. I am planning on
posting some more information/examples of my recursion methods. I will
explain how to extend the max-recursion depth to thousands-and-thousands...


Thank You!


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Antti Virtanen

unread,
Jun 20, 2006, 5:57:36 AM6/20/06
to
On 2006-06-19, Chris Thomasson <cri...@comcast.net> wrote:

> Here is a "simple" method for using the preprocessor to generate code via.
> recursion. I have a very quick and dirty example of how you can use the
> recursion facilities to automatically generate partial or explicit template
> specializations for "mechanical looking code"; such as "typelist creation
> templates", this is the example I used in my test code. Anyway, what do you
> think of my experimental recursion implementation?

There are a few things to consider, maybe you have already thought about them.

Does this make the code better in some way (more efficient, less errors)?
Is it more readable? What happens when "mechanical looking" code needs
modifications and you have to add something non mechanical to it? In
this case, one would probably have to remove the code generation and make
things manually.

Do you really need #define or would some clever use of templates suffice?
Template metaprogramming offers very elegant ways to construct many
things and Boost libaries offer many metaprogramming facilities for free
use.

Finally, #define is not safe and there's little you can do about it.
This thing only works if there are no named symbols which overlap with your
#defines, so essentially you introduce new reserved words to the language.
There are ways to deal with this, but it is not very elegant. I don't say
one must never do these things, but use #define to generate code with
caution. My way to make it "safe" looks something like this:

#ifdef my_define_magic
// for some reason there is already a symbol which we want to use in
// our #define magic so let's put here something that will not compile
the matrix has you
#endif
// now the define magic
#define my_define_magic magico

// using the #define magic here

// now undefine our magic so that it will not affect anything after
// this point during the compilation
#undef my_define_magic

--
// Antti Virtanen -//- http://www.students.tut.fi/~virtanea

Gene Bushuyev

unread,
Jun 20, 2006, 5:49:54 AM6/20/06
to
"Chris Thomasson" <cri...@comcast.net> wrote in message
news:TfCdnW5DTfWUKAjZ...@comcast.com...

>
> Here is a "simple" method for using the preprocessor to generate code via.
> recursion. I have a very quick and dirty example of how you can use the
> recursion facilities to automatically generate partial or explicit template
> specializations for "mechanical looking code"; such as "typelist creation
> templates", this is the example I used in my test code. Anyway, what do you
> think of my experimental recursion implementation?

It looks like abomination to me. I don't think anybody but author will read
pages of macros trying to understand what's going on. Macros are evil, they
should be avoided by all possible means. When a big portion of code can be
automated, it should be done with code generation tools, not with macros.

--
Gene Bushuyev (www.gbresearch.com)
----------------------------------------------------------------
To see what is in front of one's nose needs a constant struggle ~ George Orwell

Francis Glassborow

unread,
Jun 20, 2006, 9:44:18 AM6/20/06
to
In article <TfCdnW5DTfWUKAjZ...@comcast.com>, Chris
Thomasson <cri...@comcast.net> writes

> If you want to set a deeper recursion depth you will have to add-on
> to the
> VZMETAPP_ENCODING and VZPPMETA_RECURSE family of macros. I am
> planning on
> posting some more information/examples of my recursion methods. I will
> explain how to extend the max-recursion depth to thousands-and-
> thousands...
>
>
Before posting anything more on the subject here, I think you should
check to find if there is any interest. Your code seems to be an
extremely pre-processor intense mechanism that is, effectively, pure C.
IIUC the problems you are addressing have already been addressed in
'Modern C++ Design' by Andrei Alexandrescu where he largely uses
template technology. Quite apart from anything else, I find his approach
(though quite tough) to be more transparent and more maintainable.

Debugging template code is pretty tough, debugging recursive
pre-processor macros is not somewhere I would voluntarily go if there
were any better option.

Before providing us with a solution could you provide at least one real
world problem that it addresses.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/
youcandoit/projects

Pavel Vozenilek

unread,
Jun 21, 2006, 5:54:44 AM6/21/06
to

"Chris Thomasson" wrote:

> Any comments/tips/tricks are welcome... I just started messing around with
> this preprocessor meta-programming thing, I may need major help!
>

Boost.Preprocessor library:
http://www.boost.org/libs/preprocessor/doc/index.html
may be what you are looking for.

It is written by an expert, is used in real world,
has documentation and can be easily extracted
from the Boost collection.
/Pavel

David Abrahams

unread,
Jun 21, 2006, 5:56:25 AM6/21/06
to
"Chris Thomasson" <cri...@comcast.net> writes:

> Here is a "simple" method for using the preprocessor to generate code via.
> recursion. I have a very quick and dirty example of how you can use the
> recursion facilities to automatically generate partial or explicit template
> specializations for "mechanical looking code"; such as "typelist creation
> templates", this is the example I used in my test code. Anyway, what do you
> think of my experimental recursion implementation?
>
> Can you compile it?
>
>
> Any comments/tips/tricks are welcome... I just started messing around with
> this preprocessor meta-programming thing, I may need major help!

I really suggest you look at the Boost Preprocessor library:
http://www.boost.org/libs/preprocessor

The tutorial, which you can find excerpted from "C++ Template
Metaprogramming" on the book's website, gives a pretty good overview
of how to do exactly this kind of "mechanical code generation" using
the library. http://boost-consulting.com/mplbook

The library is specifically designed to be portable to a broad
spectrum of real-world (i.e. buggy -- most of them are, unfortunately)
preprocessors, so it's an especially great way to do this sort of
thing if you're writing portable code.

Paul Mensonides, the library's primary author and maintainer, has
plumbed the depths of the preprocessor and come up with even more
elegant ways to use it. His Chaos library requires a conforming
preprocessor, though. http://sourceforge.net/projects/chaos-pp.

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Chris Thomasson

unread,
Jun 21, 2006, 6:09:54 AM6/21/06
to
"Francis Glassborow" <fra...@robinton.demon.co.uk> wrote in message
news:517BjdoV...@robinton.demon.co.uk...

> In article <TfCdnW5DTfWUKAjZ...@comcast.com>, Chris
> Thomasson <cri...@comcast.net> writes
>> If you want to set a deeper recursion depth you will have to add-on
>> to the
>> VZMETAPP_ENCODING and VZPPMETA_RECURSE family of macros. I am
>> planning on
>> posting some more information/examples of my recursion methods. I will
>> explain how to extend the max-recursion depth to thousands-and-
>> thousands...
>>
>>
> Before posting anything more on the subject here, I think you should
> check to find if there is any interest.

;)


> Your code seems to be an
> extremely pre-processor intense mechanism that is, effectively, pure C.
> IIUC the problems you are addressing have already been addressed in
> 'Modern C++ Design' by Andrei Alexandrescu where he largely uses
> template technology. Quite apart from anything else, I find his approach
> (though quite tough) to be more transparent and more maintainable.
>
> Debugging template code is pretty tough, debugging recursive
> pre-processor macros is not somewhere I would voluntarily go if there
> were any better option.
>
> Before providing us with a solution could you provide at least one real
> world problem that it addresses.

Humm. Okay, consider the following:


// Andrei's TypeList
struct TypeListNull {
};

template< typename Type1, typename Type2 = TypeListNull >
struct TypeListImpl {
typedef Type1 tType;
typedef Type2 tNext;
};

// A template for creating TypeListImpl's with 1-16 members
template<typename, typename, typename, typename,
typename, typename, typename, typename,
typename, typename, typename, typename,
typename, typename, typename, typename>
struct TypeList;

Now we have to define the TypeList template and "all" of its 15 partial
specializations:


// TypeList Depth: 16
template<typename Type1 = TypeListNull,
typename Type2 = TypeListNull,
typename Type3 = TypeListNull,
typename Type4 = TypeListNull,
typename Type5 = TypeListNull,
typename Type6 = TypeListNull,
typename Type7 = TypeListNull,
typename Type8 = TypeListNull,
typename Type9 = TypeListNull,
typename Type10 = TypeListNull,
typename Type11 = TypeListNull,
typename Type12 = TypeListNull,
typename Type13 = TypeListNull,
typename Type14 = TypeListNull,
typename Type15 = TypeListNull,
typename Type16 = TypeListNull>
struct TypeList {
typedef TypeListImpl<Type1,
TypeListImpl<Type2,
TypeListImpl<Type3,
TypeListImpl<Type4,
TypeListImpl<Type5,
TypeListImpl<Type6,
TypeListImpl<Type7,
TypeListImpl<Type8,
TypeListImpl<Type9,
TypeListImpl<Type10,
TypeListImpl<Type11,
TypeListImpl<Type12,
TypeListImpl<Type13,
TypeListImpl<Type14,
TypeListImpl<Type15,
TypeListImpl<Type16
> > > > > > > > > > > > > > > > tResult;
};


We now have to add the partial specializations 1-15:

// TypeList Depth: 15
template<typename Type1,
typename Type2,
typename Type3,
typename Type4,
typename Type5,
typename Type6,
typename Type7,
typename Type8,
typename Type9,
typename Type10,
typename Type11,
typename Type12,
typename Type13,
typename Type14,
typename Type15>
struct TypeList<
Type1, Type2, Type3, Type4,
Type5, Type6, Type7, Type8,
Type9, Type10, Type11, Type12,
Type13, Type14, Type15, TypeListNull > {

typedef TypeListImpl<Type1,
TypeListImpl<Type2,
TypeListImpl<Type3,
TypeListImpl<Type4,
TypeListImpl<Type5,
TypeListImpl<Type6,
TypeListImpl<Type7,
TypeListImpl<Type8,
TypeListImpl<Type9,
TypeListImpl<Type10,
TypeListImpl<Type11,
TypeListImpl<Type12,
TypeListImpl<Type13,
TypeListImpl<Type14,
TypeListImpl<Type15
> > > > > > > > > > > > > > > tResult;
};

We go "on and on" until we reach 1. IMHO, this is an example of "mechanical
looking code", and its a "pain to type out all of those partial
specializations"...


My ad-hoc solution attempts to addresses this issue by "automatically
generating the TypeList template and all of its partial specializations".
So, instead of manually creating the template and specializations, one could
make use of my template generator, like this:

MY_TEMPLATE_GENERATOR(TypeList, 16, Type, TypeListImpl, TypeListNull)


Now we the TypeList template and all of its partial specializations are
completely generated. I think that this could "possibly" come in handy... If
you wanted to create a TypeList template that could handle hundreds of


Any thoughts?

P.S.

Imagine trying to "manually create" the following template:

MY_TEMPLATE_GENERATOR(TypeList, 512, Type, TypeListImpl, TypeListNull)

Yikes!!!!!

Reply all
Reply to author
Forward
0 new messages