example-typelist.cpp revision a5728872c7702ddd09537c95bc3cbd20e1f2fb09
1a5728872c7702ddd09537c95bc3cbd20e1f2fb09Daniel Dunbar// RUN: %clang_cc1 -fsyntax-only -verify %s 2d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor 36d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor// A simple cons-style typelist 4d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregorstruct nil { }; 5d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor 6d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregortemplate<typename Head, typename Tail = nil> 7d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregorstruct cons { 8d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor typedef Head head; 9d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor typedef Tail tail; 10d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor}; 11d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor 126d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor// is_same trait, for testing 136d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregortemplate<typename T, typename U> 146d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorstruct is_same { 156d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor static const bool value = false; 166d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor}; 176d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 186d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregortemplate<typename T> 196d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorstruct is_same<T, T> { 206d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor static const bool value = true; 216d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor}; 226d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 23d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor// metaprogram that computes the length of a list 24d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregortemplate<typename T> struct length; 25d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor 26d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregortemplate<typename Head, typename Tail> 27d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregorstruct length<cons<Head, Tail> > { 28d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor static const unsigned value = length<Tail>::value + 1; 29d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor}; 30d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor 31d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregortemplate<> 32d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregorstruct length<nil> { 33d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor static const unsigned value = 0; 34d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor}; 35d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor 36d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregortypedef cons<unsigned char, 37d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor cons<unsigned short, 38d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor cons<unsigned int, 39d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregor cons<unsigned long> > > > unsigned_inttypes; 40d708c72e3e5186662fb0045d2bd666bfd93a013dDouglas Gregorint length0[length<unsigned_inttypes>::value == 4? 1 : -1]; 416d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 426d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor// metaprogram that reverses a list 436d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 446d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor// FIXME: I would prefer that this be a partial specialization, but 456d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor// that requires partial ordering of class template partial 466d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor// specializations. 476d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregortemplate<typename T> 486d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorclass reverse { 496d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor typedef typename reverse<typename T::tail>::type reversed_tail; 506d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 516d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor typedef typename reverse<typename reversed_tail::tail>::type most_of_tail; 526d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 536d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorpublic: 546d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor typedef cons<typename reversed_tail::head, 556d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor typename reverse<cons<typename T::head, most_of_tail> >::type> type; 566d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor}; 576d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 586d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregortemplate<typename Head> 596d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorclass reverse<cons<Head> > { 606d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorpublic: 616d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor typedef cons<Head> type; 626d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor}; 636d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 646d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregortemplate<> 656d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorclass reverse<nil> { 666d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorpublic: 676d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor typedef nil type; 686d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor}; 696d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 706d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorint reverse0[is_same<reverse<unsigned_inttypes>::type, 716d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor cons<unsigned long, 726d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor cons<unsigned int, 736d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor cons<unsigned short, 746d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor cons<unsigned char> > > > >::value? 1 : -1]; 756d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 766d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor// metaprogram that finds a type within a list 776d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 786d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor// FIXME: I would prefer that this be a partial specialization, but 796d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor// that requires partial ordering of class template partial 806d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor// specializations. 816d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregortemplate<typename List, typename T> 826d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorstruct find : find<typename List::tail, T> { }; 836d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 846d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregortemplate<typename Tail, typename T> 856d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorstruct find<cons<T, Tail>, T> { 866d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor typedef cons<T, Tail> type; 876d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor}; 886d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 896d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregortemplate<typename T> 906d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorstruct find<nil, T> { 916d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor typedef nil type; 926d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor}; 936d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 946d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorint find0[is_same<find<unsigned_inttypes, unsigned int>::type, 956d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor cons<unsigned int, cons<unsigned long> > >::value? 966d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 1 : -1]; 976d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregorint find1[is_same<find<unsigned_inttypes, int>::type, nil>::value? 1 : -1]; 986d968e89411406f0fd22ae69c77c79a425e2de6fDouglas Gregor 99