1 // RUN: %clang_cc1 -fsyntax-only -verify %s
2 // expected-no-diagnostics
3 
4 // A simple cons-style typelist
5 struct nil { };
6 
7 template<typename Head, typename Tail = nil>
8 struct cons {
9   typedef Head head;
10   typedef Tail tail;
11 };
12 
13 // is_same trait, for testing
14 template<typename T, typename U>
15 struct is_same {
16   static const bool value = false;
17 };
18 
19 template<typename T>
20 struct is_same<T, T> {
21   static const bool value = true;
22 };
23 
24 // metaprogram that computes the length of a list
25 template<typename T> struct length;
26 
27 template<typename Head, typename Tail>
28 struct length<cons<Head, Tail> > {
29   static const unsigned value = length<Tail>::value + 1;
30 };
31 
32 template<>
33 struct length<nil> {
34   static const unsigned value = 0;
35 };
36 
37 typedef cons<unsigned char,
38              cons<unsigned short,
39                   cons<unsigned int,
40                        cons<unsigned long> > > > unsigned_inttypes;
41 int length0[length<unsigned_inttypes>::value == 4? 1 : -1];
42 
43 // metaprogram that reverses a list
44 
45 // FIXME: I would prefer that this be a partial specialization, but
46 // that requires partial ordering of class template partial
47 // specializations.
48 template<typename T>
49 class reverse {
50   typedef typename reverse<typename T::tail>::type reversed_tail;
51 
52   typedef typename reverse<typename reversed_tail::tail>::type most_of_tail;
53 
54 public:
55   typedef cons<typename reversed_tail::head,
56                typename reverse<cons<typename T::head, most_of_tail> >::type> type;
57 };
58 
59 template<typename Head>
60 class reverse<cons<Head> > {
61 public:
62   typedef cons<Head> type;
63 };
64 
65 template<>
66 class reverse<nil> {
67 public:
68   typedef nil type;
69 };
70 
71 int reverse0[is_same<reverse<unsigned_inttypes>::type,
72                      cons<unsigned long,
73                           cons<unsigned int,
74                                cons<unsigned short,
75                                     cons<unsigned char> > > > >::value? 1 : -1];
76 
77 // metaprogram that finds a type within a list
78 
79 // FIXME: I would prefer that this be a partial specialization, but
80 // that requires partial ordering of class template partial
81 // specializations.
82 template<typename List, typename T>
83 struct find : find<typename List::tail, T> { };
84 
85 template<typename Tail, typename T>
86 struct find<cons<T, Tail>, T> {
87   typedef cons<T, Tail> type;
88 };
89 
90 template<typename T>
91 struct find<nil, T> {
92   typedef nil type;
93 };
94 
95 int find0[is_same<find<unsigned_inttypes, unsigned int>::type,
96                        cons<unsigned int, cons<unsigned long> > >::value?
97              1 : -1];
98 int find1[is_same<find<unsigned_inttypes, int>::type, nil>::value? 1 : -1];
99 
100