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