12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// RUN: %clang_cc1 -fsyntax-only -verify %s
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// expected-no-diagnostics
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A simple cons-style typelist
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct nil { };
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate<typename Head, typename Tail = nil>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct cons {
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  typedef Head head;
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef Tail tail;
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// is_same trait, for testing
14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)template<typename T, typename U>
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)struct is_same {
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static const bool value = false;
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T>
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct is_same<T, T> {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const bool value = true;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// metaprogram that computes the length of a list
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T> struct length;
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)template<typename Head, typename Tail>
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct length<cons<Head, Tail> > {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const unsigned value = length<Tail>::value + 1;
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<>
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct length<nil> {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const unsigned value = 0;
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef cons<unsigned char,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             cons<unsigned short,
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  cons<unsigned int,
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       cons<unsigned long> > > > unsigned_inttypes;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int length0[length<unsigned_inttypes>::value == 4? 1 : -1];
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// metaprogram that reverses a list
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FIXME: I would prefer that this be a partial specialization, but
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// that requires partial ordering of class template partial
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// specializations.
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T>
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class reverse {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef typename reverse<typename T::tail>::type reversed_tail;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef typename reverse<typename reversed_tail::tail>::type most_of_tail;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)public:
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef cons<typename reversed_tail::head,
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               typename reverse<cons<typename T::head, most_of_tail> >::type> type;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename Head>
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class reverse<cons<Head> > {
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)public:
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef cons<Head> type;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<>
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class reverse<nil> {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)public:
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef nil type;
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int reverse0[is_same<reverse<unsigned_inttypes>::type,
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     cons<unsigned long,
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          cons<unsigned int,
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               cons<unsigned short,
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    cons<unsigned char> > > > >::value? 1 : -1];
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// metaprogram that finds a type within a list
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// FIXME: I would prefer that this be a partial specialization, but
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// that requires partial ordering of class template partial
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// specializations.
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename List, typename T>
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct find : find<typename List::tail, T> { };
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename Tail, typename T>
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct find<cons<T, Tail>, T> {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef cons<T, Tail> type;
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)};
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)template<typename T>
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct find<nil, T> {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef nil type;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int find0[is_same<find<unsigned_inttypes, unsigned int>::type,
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       cons<unsigned int, cons<unsigned long> > >::value?
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)             1 : -1];
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int find1[is_same<find<unsigned_inttypes, int>::type, nil>::value? 1 : -1];
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)