| 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 | |