template<typename H, typename T> struct List {
typedef H Type;
typedef T Next;
};
// at<L,N>::Type returns the Nth type in the list L
//usual code:
template<typename L, unsigned int N> struct at {
typedef at<typename L::Next, N-1>::Type Type;
};
template<typename L> struct at<L, 0> {
typedef typename L::Type Type;
}
//my code:
template<typename L, unsigned int N> struct at :
at<typename L::Next, N-1> {};
template<typename L> struct at<L, 0> : L {};
my code seens to me cleaner and more "haskell like" doing the same thing usual code does but inheritance can sometimes be a invisible source of problems in meta-programming.
Any recomendations?
Sergio
[edited by - svpace on January 30, 2004 12:12:52 PM]
🔒 Locked
template meta-programming
Advertisement
Original Post
Hi, I'm working on a small template meta-programming library, for learning and probably for later real world use. currently I'm working with type lists and I thing I found a interesting ay of coding metaprograms, but I didn't find anyone else using this, so I'm wondering if there is any gotchas in my idea:
example:
Just reposting your code in [source] tags so that I can see the stuff that dissapeared because it was interpreted as HTML tags:
example
Enigma
EDIT: typo
[edited by - Enigma on January 30, 2004 11:57:37 AM]
example
template<typename H, typename T> struct List {
typedef H Type;
typedef T Next;
};
// at<L,N>::Type returns the Nth type in the list L
//usual code:
template<typename L, unsigned int N> struct at {
typedef at<typename L::Next, N-1>::Type Type;
};
template<typename L> struct at<L, 0> {
typedef typename L::Type Type;
}
//my code:
template<typename L, unsigned int N> struct at :
at<typename L::Next, N-1> {};
template<typename L> struct at<L, 0> : L {};Enigma
EDIT: typo
[edited by - Enigma on January 30, 2004 11:57:37 AM]
in the usual code there is an explicit typedef for Type, in fact it's the only thing inside "at". in my code the Type typedef is inherited from List, and this is the difference between both codes, in my code I avoid redundant typedef's by inheriting then from some base case (partial specialization), and only the base case use an explicit typedef.
the L template parameter must always be of List type, or something that implement the same typedef's otherwise there will be an compiler error
[edited by - svpace on January 30, 2004 11:40:46 PM]
the L template parameter must always be of List type, or something that implement the same typedef's otherwise there will be an compiler error
[edited by - svpace on January 30, 2004 11:40:46 PM]
The only possible problem i can see would be that you end up inheriting from Nil. If Nil has a Type typedef in it, it may compile even though you wouldnt really want it to. So you have to be careful as to the interface of the Nil type (the same applies to the non-inheritence method too, though).
Apart from that, I think both methods are valid depending on how you would want to use the at template. If you require access to the ''Next typedef'' as well as the ''Type typedef'' through the at template, then i would say using inheritance is the way to go. If, however, you will only be using the Type typedef, then i would argue that the method not using inheritence is clearer to the reader, as it provides the at template with its own solid interface, rather than relying on the List interface.
Apart from that, I think both methods are valid depending on how you would want to use the at template. If you require access to the ''Next typedef'' as well as the ''Type typedef'' through the at template, then i would say using inheritance is the way to go. If, however, you will only be using the Type typedef, then i would argue that the method not using inheritence is clearer to the reader, as it provides the at template with its own solid interface, rather than relying on the List interface.
Sorry for the delay but you know that damm real life, always getting in the way.
antareus: got the Loki library, real great stuff, but they use the "usual code" too.
danielf: real example? well as I said I''m just begining to learn this stuff so be patient. type lists can be good for adding some reflexitivity in classes, or in some place where you need to tranform an index in some type, database maybe... it''s vague and I agree with you, actually I never used type lists... yet. But I already used some very interesting loop unroling metaprogramming to optimize a vector library I was working with. For now I''m just learning and waiting to see what comes up. If anyone have some intersting examples I will apreciate.
Jing: about the Nil inheritance my code was not very complete by the time of my first post
there are some specializations of "at" to handle the Nil case. as for the readability I was so happy that my code was easier to read than usual code...
. well I guess coding style is very personal stuff indeed, but thanks for the input anyway.
Everybody: after some more exploratory programming I came up with some discoveries. the "my code" style seens to have some disvantages, it can''t be use for final types, types that will be actually be used for normal programming, for example consider the meta-if:
the "my code" style would provide a subtype of A witch don''t have a string constructor unless someone know how to inherit constructors, candidates?
also it creates some typesafe issues, some metafunctions (structs) use direct reference to List to avoid the Nil case
in these cases as "at"(or any other of the list metafunction) actually became an List instead of providing a List type foo will not recognize it and will pass it to the general case (first one) as templates don''t support polimorfism. it is possible to generalize the description to some templatized template parameter:
but we open space for errors as any two parameter template could be used. Any recomendations? typesafety or flexibility?
Well that''s it for now, keep talking(typing) I''m all ears(eyes)
Sérgio
antareus: got the Loki library, real great stuff, but they use the "usual code" too.
danielf: real example? well as I said I''m just begining to learn this stuff so be patient. type lists can be good for adding some reflexitivity in classes, or in some place where you need to tranform an index in some type, database maybe... it''s vague and I agree with you, actually I never used type lists... yet. But I already used some very interesting loop unroling metaprogramming to optimize a vector library I was working with. For now I''m just learning and waiting to see what comes up. If anyone have some intersting examples I will apreciate.
Jing: about the Nil inheritance my code was not very complete by the time of my first post
Everybody: after some more exploratory programming I came up with some discoveries. the "my code" style seens to have some disvantages, it can''t be use for final types, types that will be actually be used for normal programming, for example consider the meta-if:
//usual code
template<bool B, typename T, typename F> struct If {
typedef T Type;
};
template<typename T, typename F> struct If<false, T, F> {
typedef F, Type;
}
If<true, A, B>::Type a("class A");
//my code
template<bool B, typename T, typename F> struct If : T {};
template<typename T, typename F> struct If<false, T, F> : F{};
If<true, A, B> a("class A");
the "my code" style would provide a subtype of A witch don''t have a string constructor unless someone know how to inherit constructors, candidates?
also it creates some typesafe issues, some metafunctions (structs) use direct reference to List to avoid the Nil case
template<typename L> struct foo {};
template<typename H, typename T> foo< List<H, T> > { /*stuff*/ }
template<typename H> foo< List<H, Nil> > { /*more stuff*/ }
in these cases as "at"(or any other of the list metafunction) actually became an List instead of providing a List type foo will not recognize it and will pass it to the general case (first one) as templates don''t support polimorfism. it is possible to generalize the description to some templatized template parameter:
template<template<typename H, typename T> class L> struct foo{};
but we open space for errors as any two parameter template could be used. Any recomendations? typesafety or flexibility?
Well that''s it for now, keep talking(typing) I''m all ears(eyes)
Sérgio
quote:
Original post by svpace
antareus: got the Loki library, real great stuff, but they use the "usual code" too.
Sérgio
Loki does exactly what you do, Loki::TL::Typelist is just like your List struct. There are several meta-templates to index the typelist, I''ve demostrated a method to create a class from a typelist, written an automated interpretor/executor using a function-signature meta-template, and created a mechanism to produce run-time data from a compile-time typelist. I must admit I haven''t paid the library much attention lately, and we are long over due for an update (that includes these new things).
Ohhh, that mechanism of using inheritence works for most cases, but breaks down when you need to create two children. Sometimes, the two children will, by coincidence, have the same parameters, and you can''t inherit from the same class twice. My data generator worked that why at first.
Boost also has a meta-template programming library; I think there goal was to make the syntax of functional programming in C++ more like traditional functional syntax (the C++ way is very clumsy). Though I haven''t used it much.
- Magmai Kai Holmlor
Not For Rent
[Look for information | GDNet Start Here | GDNet Search Tool | GDNet FAQ | MSDN RTF[L] | SGI STL Docs | STFW | Asking Smart Questions ]
[Free C++ Libraries | Boost | ACE | Loki | MTL | Blitz++ | wxWindows| Spirit(xBNF)]
[Free C Libraries | zlib ]
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement