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