1// RUN: %clang_cc1 -fsyntax-only -verify %s
2// expected-no-diagnostics
3
4// A simple cons-style typelist
5struct nil { };
6
7template<typename Head, typename Tail = nil>
8struct cons {
9  typedef Head head;
10  typedef Tail tail;
11};
12
13// is_same trait, for testing
14template<typename T, typename U>
15struct is_same {
16  static const bool value = false;
17};
18
19template<typename T>
20struct is_same<T, T> {
21  static const bool value = true;
22};
23
24// metaprogram that computes the length of a list
25template<typename T> struct length;
26
27template<typename Head, typename Tail>
28struct length<cons<Head, Tail> > {
29  static const unsigned value = length<Tail>::value + 1;
30};
31
32template<>
33struct length<nil> {
34  static const unsigned value = 0;
35};
36
37typedef cons<unsigned char,
38             cons<unsigned short,
39                  cons<unsigned int,
40                       cons<unsigned long> > > > unsigned_inttypes;
41int 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.
48template<typename T>
49class 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
54public:
55  typedef cons<typename reversed_tail::head,
56               typename reverse<cons<typename T::head, most_of_tail> >::type> type;
57};
58
59template<typename Head>
60class reverse<cons<Head> > {
61public:
62  typedef cons<Head> type;
63};
64
65template<>
66class reverse<nil> {
67public:
68  typedef nil type;
69};
70
71int 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.
82template<typename List, typename T>
83struct find : find<typename List::tail, T> { };
84
85template<typename Tail, typename T>
86struct find<cons<T, Tail>, T> {
87  typedef cons<T, Tail> type;
88};
89
90template<typename T>
91struct find<nil, T> {
92  typedef nil type;
93};
94
95int find0[is_same<find<unsigned_inttypes, unsigned int>::type,
96                       cons<unsigned int, cons<unsigned long> > >::value?
97             1 : -1];
98int find1[is_same<find<unsigned_inttypes, int>::type, nil>::value? 1 : -1];
99
100