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