1/* { dg-do run } */
2
3#include <stdlib.h>
4
5struct null_type {};
6
7inline const null_type cnull() { return null_type(); }
8
9template <class TT> struct cons;
10class tuple;
11
12template< int N >
13struct get_class {
14  template<class TT >
15  inline static int& get(cons<TT>& t)
16  {
17    return get_class<N-1>::template get(t.tail);
18  }
19};
20
21template<>
22struct get_class<0> {
23  template<class TT>
24  inline static int& get(cons<TT>& t)
25  {
26    return t.head;
27  }
28};
29
30template<int N, class T>
31struct element
32{
33private:
34  typedef typename T::tail_type Next;
35public:
36  typedef typename element<N-1, Next>::type type;
37};
38
39template<class T>
40struct element<0,T>
41{
42  typedef int type;
43};
44
45template<int N, class TT>
46inline int& get(cons<TT>& c) {
47  return get_class<N>::template get(c);
48}
49
50template <class TT>
51struct cons {
52  typedef TT tail_type;
53
54  int head;
55  tail_type tail;
56
57  cons() : head(), tail() {}
58
59  template <class T1, class T2, class T3, class T4>
60  cons( T1& t1, T2& t2, T3& t3, T4& t4 )
61    : head (t1),
62      tail (t2, t3, t4, cnull())
63      {}
64};
65
66template <>
67struct cons<null_type> {
68  typedef null_type tail_type;
69
70  int head;
71
72  cons() : head() {}
73
74  template<class T1>
75  cons(T1& t1, const null_type&, const null_type&, const null_type&)
76  : head (t1) {}
77};
78
79template <class T0, class T1, class T2, class T3>
80struct map_tuple_to_cons
81{
82  typedef cons<typename map_tuple_to_cons<T1, T2, T3, null_type>::type> type;
83};
84
85template <>
86struct map_tuple_to_cons<null_type, null_type, null_type, null_type>
87{
88  typedef null_type type;
89};
90
91class tuple :
92  public map_tuple_to_cons<int, int, int, int>::type
93{
94public:
95  typedef typename
96    map_tuple_to_cons<int, int, int, int>::type inherited;
97
98  tuple(const int &t0,
99        const int &t1,
100        const int &t2,
101        const int &t3)
102    : inherited(t0, t1, t2, t3) {}
103};
104
105void foo(void (*boo)(int, int, int, int), tuple t)
106{
107  boo(get<0>(t), get<1>(t), get<2>(t), get<3>(t));
108}
109
110int tailcalled_t1;
111int tailcalled_t2;
112int tailcalled_t3;
113int tailcalled_t4;
114
115void print(int t1, int t2, int t3, int t4)
116{
117  tailcalled_t1 = t1;
118  tailcalled_t2 = t2;
119  tailcalled_t3 = t3;
120  tailcalled_t4 = t4;
121}
122
123int main ()
124{
125  tuple t(1,2,3,4);
126  foo(print, t);
127
128  if( (get<0>(t) != tailcalled_t1)
129    ||(get<1>(t) != tailcalled_t2)
130    ||(get<2>(t) != tailcalled_t3)
131      ||(get<3>(t) != tailcalled_t4))
132      abort();
133
134  return 0;
135}
136