![]() |
|
|
Welcome to the { mindfrost82.com } forums. You are currently viewing our boards as a guest which gives you limited access to view most discussions and access our other features. By joining our free community you will have access to post topics, communicate privately with other members (PM), respond to polls, upload content and access many other special features. Registration is fast, simple and absolutely free so please, join our community today! If you have any problems with the registration process or your account login, please contact contact us. |
|
|||||||
![]() |
|
|
LinkBack | Thread Tools | Search this Thread | Display Modes |
|
|||
|
C++0x Variadic Templates
Hi,
I've been lately playing with variadic templates lately and tried to find it's limits (by using g++ 4.4.0 experimental) I am especially interessted in the template meta programming usability aspects of this extension to the standard. I have been able to generate at compiletime type lists with 256k elements and transform this list with a compilation time of a few seconds on my machine. But one thing really made me wondering. In this paper: http://www.open-std.org/jtc1/sc22/wg...2004/n1704.pdf (Variadic Templates: Exploring the Design Space) Douglas Gregor, Jaakko Järvi and Gary Powell where talking about accessing the nth element in a parameter pack. Actually this would be comparable to the boost.mpl at implementation. Imho this is one of the features which should be really easy to implement and so I am wondering why this has been not taken over into the standard. The compilation time will be really horrible for bigger type lists (actually if they're greater than 5 it's already starting to get really worse (on g++ 4.4 at least)) The reason for this is obvious. The compiler has to intatiate recursively m instances of at in a list of n types. Where in most implementations n = m. (Which can be improved by "loop unrolling") I have been implementing a quite fast one where I can access the 500th element in the parameter pack with a compilation time of only about 26 seconds compilation time. But this is actually wasted resources for the compiler if you can access other items faster. I am not sure how much it is used but i'd expect that there might be good uses for this kind of feature (accessing the nth element in a type list) supported by the compiler. Since it will improve meta programming compilation times a lot. I'd be nice to hear your opinion about this. Also please let me know if I have been missing something what would make this possible without any changes of the current draft for the variadic templates. With best regards, Vinzenz Feenstra -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: C++0x Variadic Templates
on Mon Aug 25 2008, "evilissimo-AT-googlemail.com" <evilissimo-AT-googlemail.com> wrote: > Hi, > > I've been lately playing with variadic templates lately and tried to > find it's limits (by using g++ 4.4.0 experimental) > I am especially interessted in the template meta programming usability > aspects of this extension to the standard. It's about time somebody started looking at this! > I have been able to generate at compiletime type lists with 256k > elements and transform this list with a compilation time of a few > seconds on my machine. > But one thing really made me wondering. In this paper: > http://www.open-std.org/jtc1/sc22/wg...2004/n1704.pdf > (Variadic Templates: Exploring the Design Space) Douglas Gregor, > Jaakko Järvi and Gary Powell where talking about accessing the nth > element in a parameter pack. Actually this would be comparable to the > boost.mpl at implementation. > > Imho this is one of the features which should be really easy to > implement and so I am wondering why this has been not taken over into > the standard. The compilation time will be really horrible for bigger > type lists (actually if they're greater than 5 it's already starting > to get really worse (on g++ 4.4 at least)) > > The reason for this is obvious. The compiler has to intatiate > recursively m instances of at in a list of n types. Where in most > implementations n = m. If that's because of the O(N^2) instantiation characteristic, you might want to look at this thread: http://news.gmane.org/find-root.php?...sulting.com%3e > (Which can be improved by "loop unrolling") I > have been implementing a quite fast one where I can access the 500th > element in the parameter pack with a compilation time of only about 26 > seconds compilation time. Hmm, even a naive implementation goes much faster than that for me. I'm using conceptgcc to test on a 2.16 Ghz core duo with 2G of RAM: for x in 0 1 2; do time conceptgcc -ftemplate-depth-600 get.cpp -o /tmp/get; done real 0m3.912s user 0m3.188s sys 0m0.688s real 0m3.899s user 0m3.108s sys 0m0.740s real 0m3.865s user 0m3.128s sys 0m0.736s === CODE: === template <class... T> struct vector { }; template <unsigned N, class C> struct get; template <unsigned N, class H, class... T> struct get<N, vector<H, T...> > : get<N-1, vector<T...> > { }; template <class H, class... T> struct get<0, vector<H, T...> > { typedef H type; }; template <int x> struct i; typedef vector<> test0; typedef get<0,vector<int> >::type test1; typedef vector< i<0>, i<1>, i<2>, i<3>, i<4>, i<5>, i<6>, i<7>, i<8>, i<9>, i<10>, i<11>, i<12>, i<13>, i<14>, i<15>, i<16>, i<17>, i<18>, i<19>, i<20>, i<21>, i<22>, i<23>, i<24>, i<25>, i<26>, i<27>, i<28>, i<29>, i<30>, i<31>, i<32>, i<33>, i<34>, i<35>, i<36>, i<37>, i<38>, i<39>, i<40>, i<41>, i<42>, i<43>, i<44>, i<45>, i<46>, i<47>, i<48>, i<49>, i<50>, i<51>, i<52>, i<53>, i<54>, i<55>, i<56>, i<57>, i<58>, i<59>, i<60>, i<61>, i<62>, i<63>, i<64>, i<65>, i<66>, i<67>, i<68>, i<69>, i<70>, i<71>, i<72>, i<73>, i<74>, i<75>, i<76>, i<77>, i<78>, i<79>, i<80>, i<81>, i<82>, i<83>, i<84>, i<85>, i<86>, i<87>, i<88>, i<89>, i<90>, i<91>, i<92>, i<93>, i<94>, i<95>, i<96>, i<97>, i<98>, i<99>, i<100>, i<101>, i<102>, i<103>, i<104>, i<105>, i<106>, i<107>, i<108>, i<109>, i<110>, i<111>, i<112>, i<113>, i<114>, i<115>, i<116>, i<117>, i<118>, i<119>, i<120>, i<121>, i<122>, i<123>, i<124>, i<125>, i<126>, i<127>, i<128>, i<129>, i<130>, i<131>, i<132>, i<133>, i<134>, i<135>, i<136>, i<137>, i<138>, i<139>, i<140>, i<141>, i<142>, i<143>, i<144>, i<145>, i<146>, i<147>, i<148>, i<149>, i<150>, i<151>, i<152>, i<153>, i<154>, i<155>, i<156>, i<157>, i<158>, i<159>, i<160>, i<161>, i<162>, i<163>, i<164>, i<165>, i<166>, i<167>, i<168>, i<169>, i<170>, i<171>, i<172>, i<173>, i<174>, i<175>, i<176>, i<177>, i<178>, i<179>, i<180>, i<181>, i<182>, i<183>, i<184>, i<185>, i<186>, i<187>, i<188>, i<189>, i<190>, i<191>, i<192>, i<193>, i<194>, i<195>, i<196>, i<197>, i<198>, i<199>, i<200>, i<201>, i<202>, i<203>, i<204>, i<205>, i<206>, i<207>, i<208>, i<209>, i<210>, i<211>, i<212>, i<213>, i<214>, i<215>, i<216>, i<217>, i<218>, i<219>, i<220>, i<221>, i<222>, i<223>, i<224>, i<225>, i<226>, i<227>, i<228>, i<229>, i<230>, i<231>, i<232>, i<233>, i<234>, i<235>, i<236>, i<237>, i<238>, i<239>, i<240>, i<241>, i<242>, i<243>, i<244>, i<245>, i<246>, i<247>, i<248>, i<249>, i<250>, i<251>, i<252>, i<253>, i<254>, i<255>, i<256>, i<257>, i<258>, i<259>, i<260>, i<261>, i<262>, i<263>, i<264>, i<265>, i<266>, i<267>, i<268>, i<269>, i<270>, i<271>, i<272>, i<273>, i<274>, i<275>, i<276>, i<277>, i<278>, i<279>, i<280>, i<281>, i<282>, i<283>, i<284>, i<285>, i<286>, i<287>, i<288>, i<289>, i<290>, i<291>, i<292>, i<293>, i<294>, i<295>, i<296>, i<297>, i<298>, i<299>, i<300>, i<301>, i<302>, i<303>, i<304>, i<305>, i<306>, i<307>, i<308>, i<309>, i<310>, i<311>, i<312>, i<313>, i<314>, i<315>, i<316>, i<317>, i<318>, i<319>, i<320>, i<321>, i<322>, i<323>, i<324>, i<325>, i<326>, i<327>, i<328>, i<329>, i<330>, i<331>, i<332>, i<333>, i<334>, i<335>, i<336>, i<337>, i<338>, i<339>, i<340>, i<341>, i<342>, i<343>, i<344>, i<345>, i<346>, i<347>, i<348>, i<349>, i<350>, i<351>, i<352>, i<353>, i<354>, i<355>, i<356>, i<357>, i<358>, i<359>, i<360>, i<361>, i<362>, i<363>, i<364>, i<365>, i<366>, i<367>, i<368>, i<369>, i<370>, i<371>, i<372>, i<373>, i<374>, i<375>, i<376>, i<377>, i<378>, i<379>, i<380>, i<381>, i<382>, i<383>, i<384>, i<385>, i<386>, i<387>, i<388>, i<389>, i<390>, i<391>, i<392>, i<393>, i<394>, i<395>, i<396>, i<397>, i<398>, i<399>, i<400>, i<401>, i<402>, i<403>, i<404>, i<405>, i<406>, i<407>, i<408>, i<409>, i<410>, i<411>, i<412>, i<413>, i<414>, i<415>, i<416>, i<417>, i<418>, i<419>, i<420>, i<421>, i<422>, i<423>, i<424>, i<425>, i<426>, i<427>, i<428>, i<429>, i<430>, i<431>, i<432>, i<433>, i<434>, i<435>, i<436>, i<437>, i<438>, i<439>, i<440>, i<441>, i<442>, i<443>, i<444>, i<445>, i<446>, i<447>, i<448>, i<449>, i<450>, i<451>, i<452>, i<453>, i<454>, i<455>, i<456>, i<457>, i<458>, i<459>, i<460>, i<461>, i<462>, i<463>, i<464>, i<465>, i<466>, i<467>, i<468>, i<469>, i<470>, i<471>, i<472>, i<473>, i<474>, i<475>, i<476>, i<477>, i<478>, i<479>, i<480>, i<481>, i<482>, i<483>, i<484>, i<485>, i<486>, i<487>, i<488>, i<489>, i<490>, i<491>, i<492>, i<493>, i<494>, i<495>, i<496>, i<497>, i<498>, i<499> > v500; int main() { typedef get<499, v500>::type u; } === END CODE === Of course you could speed this up massively with some specializations to work on the first, say, 20 elements. > But this is actually wasted resources for > the compiler if you can access other items faster. Sorry, I don't understand what you mean here. Which other items? The ones near the beginning of the sequence? > I am not sure how much it is used but i'd expect that there might be > good uses for this kind of feature (accessing the nth element in a > type list) supported by the compiler. Since it will improve meta > programming compilation times a lot. > > I'd be nice to hear your opinion about this. Also please let me know > if I have been missing something what would make this possible without > any changes of the current draft for the variadic templates. Well, it's currently *possible* already. Do you mean you want to do it in O(1)? -- Dave Abrahams BoostPro Computing http://www.boostpro.com [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: C++0x Variadic Templates
[snip]
> If that's because of the O(N^2) instantiation characteristic, you might > want to look at this thread:http://news.gmane.org/find-root.php?...0A3.4060704%40... Thanks for giving me the link. Actually this is funny. I have not seen that one but that's similar to my approach. (See below) > Hmm, even a naive implementation goes much faster than that for me. I'm > using conceptgcc to test on a 2.16 Ghz core duo with 2G of RAM: [snip] > Of course you could speed this up massively with some specializations to > work on the first, say, 20 elements. Well I forgot to mention that I created a huge list (2 ^ 14 elements) at compile time. ;) The generation approach is pretty expensive for memory. Additionally I had a bug which was not accessing the 500th element but something much higher (actually no idea which one exactly), what I haven't realized because the list was so big and it compiled. > > But this is actually wasted resources for > > the compiler if you can access other items faster. > > Sorry, I don't understand what you mean here. Which other items? The > ones near the beginning of the sequence? Actually it should have been "any" instead of "other"... > Well, it's currently *possible* already. Do you mean you want to do it > in O(1)? .... and yes I meant 0(1) access. Here's my approach for the at: Code:
As you can see there are specializations for 50, 10, 5, 2 and 1, which helps me to avoid to go too deep so I don't need to use the -ftemplate- depth parameter. evilissimo@evilnotebook:~/projects/vartpl$ for i in 0 1 2; do time g++ meta.cpp -o meta -std=c++0x; done real 0m1.110s user 0m0.996s sys 0m0.116s real 0m0.855s user 0m0.812s sys 0m0.044s real 0m0.905s user 0m0.816s sys 0m0.052s Also I've implemented a tranform which was quite easy and is quite fast :) Code:
and a for_each: Code:
Not sure what the compiler makes out of it, but when I executed it with the following code but the comparation to a loop which does the same is quite impressive: The compilation time is actually 20 seconds for this code which is because of the for_each implementation. Code:
evilissimo@evilnotebook:~/projects/vartpl$ for i in 0 1 2; do time ./ meta;done 500 real 0m0.009s user 0m0.004s sys 0m0.008s 500 real 0m0.008s user 0m0.008s sys 0m0.000s 500 real 0m0.008s user 0m0.004s sys 0m0.004s versus: // which is basically the same code just "more readable" int main() { size_t count = 0; for(size_t i = 0; i < 500; ++i) ++count; std::cout << count << std::endl; return 0; } evilissimo@evilnotebook:~/projects/vartpl$ for i in 0 1 2; do time ./ meta;done 500 real 0m0.008s user 0m0.004s sys 0m0.004s 500 real 0m0.008s user 0m0.004s sys 0m0.004s 500 real 0m0.007s user 0m0.004s sys 0m0.004s I bet, that the things I've done so far are not really something new, but still I haven't found much resources about it so maybe this information about the variadic templates is a kick off for some people getting some new ideas. I would be glad to read more about it. I am still thinking of other ways using it. One thing what is quite awesome is this: template<typename Container> struct extract; template<template <typename...> class Container, typename... Args> struct extract<Container<Args...>> { enum{ size = sizeof...(Args) }; typedef vtmpl::vector< Args... > type; }; you can extract all parameters of a template. Which might be useful to transform a container type into another (exchanging allocators, or compare operators, or maybe key/value types from maps etc) Maybe I can find some more use cases which are improving the meta programming aspects. Regards, Vinzenz PS to Dave: Thanks a lot for your reply :) -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: C++0x Variadic Templates
David Abrahams wrote:
[...] > > v500; > > int main() > { > typedef get<499, v500>::type u; > } > > === END CODE === > > Of course you could speed this up massively with some specializations > to work on the first, say, 20 elements. I tried: template <int x> struct i {}; and: get<400,v500>::type a1; get<410,v500>::type a2; get<420,v500>::type a3; get<430,v500>::type a4; get<440,v500>::type a5; get<450,v500>::type a6; And this made gcc trash my swap space until my machine froze. And I've got 4GB RAM. I've tried to implement the pattern Steve Watanabe suggested, which essentially is botton-up evaluation: template<typename C> struct tail; template<typename H,typename ...T> struct tail<vector<H,T...> > { typedef vector<T...> type; }; template<typename C> struct head; template<typename H,typename ...T> struct head<vector<H,T...> > { typedef H type; }; template<unsigned N, typename T> struct get_help { typedef typename tail< typename get_help<N-1,T>::type >::type type; }; template<typename T> struct get_help< 0,T > { typedef T type; }; template<unsigned N,typename T> struct get { typedef typename get_help<N,T>::type P; typedef typename head< P >::type type; }; This creates significant less instantiations and compiles my example in ~4seconds. I am inclined to see a problem in the fact, that variadic templates as they are now, might require intricate evaluation techniques to be useable at all. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: C++0x Variadic Templates
On Aug 27, 3:45 am, Marco Manfredini <ok_nospam...@phoyd.net> wrote:
[snip] > > I tried: > template <int x> struct i {}; > and: > get<400,v500>::type a1; > get<410,v500>::type a2; > get<420,v500>::type a3; > get<430,v500>::type a4; > get<440,v500>::type a5; > get<450,v500>::type a6; > > And this made gcc trash my swap space until my machine froze. And I've > got 4GB RAM. That's why I started this discussion ;) I've just 2GB RAM and it happend to me quite often ;) [snip] > > This creates significant less instantiations and compiles my example in > ~4seconds. With my approach I've been able to compile the in less than 2 seconds on my notebook (AMD Turion x2 with 2GB RAM) evilissimo@evilnotebook:~/projects/vartpl$ for i in 0 1 2; do time g++ meta.cpp -o meta -std=c++0x; done real 0m1.793s user 0m1.188s sys 0m0.100s real 0m1.277s user 0m1.160s sys 0m0.116s real 0m1.300s user 0m1.144s sys 0m0.156s > I am inclined to see a problem in the fact, that variadic > templates as they are now, might require intricate evaluation > techniques to be useable at all. I don't think it's more complex than before, but still there will be a need to have a more compile time efficient (memory & complexity) way to access types or elements in a parameter pack of variadic templates, especially for template meta programming. No question variadics brought already loads of improvements but still I am thinking that a language supported way of accessing the nth element in a parameter pack (something like sizeof... but for indexing) would be a real improvement. But however, maybe I fail to see the major usage of template meta programming as it is not something I can use alot (altough I wish I could use it at some more places (where appropriate)). Usually I am just "playing" around with these kind of features. However it might be that the indexing is not so important but still I'd like to know what was the reason for this not being implemented, since it was thought of in the document I've linked in my initial post. Regards, Vinzenz -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Re: C++0x Variadic Templates
on Tue Aug 26 2008, "evilissimo-AT-googlemail.com" <evilissimo-AT-googlemail.com> wrote: > [snip] >> If that's because of the O(N^2) instantiation characteristic, you might >> want to look at this thread:http://news.gmane.org/find-root.php?...0A3.4060704%40... > Thanks for giving me the link. Actually this is funny. I have not seen > that one but that's similar to my approach. (See below) > >> Hmm, even a naive implementation goes much faster than that for me. I'm >> using conceptgcc to test on a 2.16 Ghz core duo with 2G of RAM: > > [snip] > >> Of course you could speed this up massively with some specializations to >> work on the first, say, 20 elements. > > Well I forgot to mention that I created a huge list (2 ^ 14 elements) > at compile time. ;) > The generation approach is pretty expensive for memory. Urr, yeah. But then it doesn't look like you were measuring the slowness of the thing you thought you were measuring. > Additionally I had a bug which was not accessing the 500th element but > something much higher (actually no idea which one exactly), what I > haven't realized because the list was so big and it compiled. > >> > But this is actually wasted resources for >> > the compiler if you can access other items faster. >> >> Sorry, I don't understand what you mean here. Which other items? The >> ones near the beginning of the sequence? > > Actually it should have been "any" instead of "other"... I still don't understand what you mean by "wasted resources" nor do I understand why the time it takes to reach a different element is relevant. >> Well, it's currently *possible* already. Do you mean you want to do it >> in O(1)? > > ... and yes I meant 0(1) access. If your compiler supports typeof() or decltype() you can do it in O(1) instantiations. See boost::mpl::vector, which is a typelist implementation on such compilers. So it seems to me to be pointless to explore C++0x metaprogramming without using all its features; C++0x is going to completely change the landscape. > Here's my approach for the at: > > [code] > #include <boost/mpl/if.hpp> > > template<typename... Types> > struct vector > { > enum { size = sizeof...(Types) }; > > }; > > namespace detail > { > template<size_t N, typename... Params> > struct at_impl; > > template<size_t N> > struct at_helper; > > template<typename T, typename... Params> > struct at_impl<0, T, Params...> > { > typedef T type; > }; > > template<size_t N, typename... Params> > struct at_impl > { > typedef typename at_helper<N>::template apply<Params...>::type > type; > }; > <sorry, no time to read it all> > As you can see there are specializations for 50, 10, 5, 2 and 1, which > helps me to avoid to go too deep so I don't need to use the -ftemplate- > depth parameter. You _do_ know that the MPL is already doing that sort of unrolling (with far fewer iterations)? If you really want to avoid depth, make the size of your list accessible in O(1) and do binary unrolling. > evilissimo@evilnotebook:~/projects/vartpl$ for i in 0 1 2; do time g++ > Maybe I can find some more use cases which are improving the meta > programming aspects. > > Regards, > Vinzenz > > PS to Dave: Thanks a lot for your reply :) it's an interesting topic. -- Dave Abrahams BoostPro Computing http://www.boostpro.com [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
![]() |
|
| Thread Tools | Search this Thread |
| Display Modes | |
|
|