Skip to main content
gamedev.net
🔒 Locked

template meta-programming

Started by svpace Jan 30, 2004 at 10:51 AM 9 replies 1.1k views
Original Post
svpace
svpace
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:
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]
Enigma
Enigma
Just reposting your code in [source] tags so that I can see the stuff that dissapeared because it was interpreted as HTML tags:

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]
SiCrane
SiCrane
How do you plan on using your at structure? It''s not much use for creating function signatures, or specializing templated classes. For example: what if you wanted to create a std::vector using the type of the third item in your typelist?
svpace
svpace
it can be something like this:


typedef List<int, List<char, List<float, Nil> > > types;
std::vector< at<types,2>::Type> vector_of_type_2; // 0 based index




[edited by - svpace on January 30, 2004 10:23:44 PM]
SiCrane
SiCrane
Except you can''t do that. You don''t have a Type typedef in your at struct.
svpace
svpace
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]
antareus
antareus
Have you looked at the Loki library? Alecsandru talks about some uses of type lists in his Modern C++ Design book. Might want to see what sort of things the Loki documentation says.
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
danielf
danielf
Your code is very interesting... I have never thought of it... But really, I cant see any case in where it might be usefull. Can you give an example? I am really interested...

Thank you.
Jingo
Jingo
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.
svpace
svpace
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:

//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



Shannon Barber
Shannon Barber
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 ]

The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.