1 /* { dg-do run } */
2 
3 #include <stdlib.h>
4 
5 struct null_type {};
6 
cnull()7 inline const null_type cnull() { return null_type(); }
8 
9 template <class TT> struct cons;
10 class tuple;
11 
12 template< int N >
13 struct get_class {
14   template<class TT >
getget_class15   inline static int& get(cons<TT>& t)
16   {
17     return get_class<N-1>::template get(t.tail);
18   }
19 };
20 
21 template<>
22 struct get_class<0> {
23   template<class TT>
24   inline static int& get(cons<TT>& t)
25   {
26     return t.head;
27   }
28 };
29 
30 template<int N, class T>
31 struct element
32 {
33 private:
34   typedef typename T::tail_type Next;
35 public:
36   typedef typename element<N-1, Next>::type type;
37 };
38 
39 template<class T>
40 struct element<0,T>
41 {
42   typedef int type;
43 };
44 
45 template<int N, class TT>
46 inline int& get(cons<TT>& c) {
47   return get_class<N>::template get(c);
48 }
49 
50 template <class TT>
51 struct 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 
66 template <>
67 struct 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 
79 template <class T0, class T1, class T2, class T3>
80 struct map_tuple_to_cons
81 {
82   typedef cons<typename map_tuple_to_cons<T1, T2, T3, null_type>::type> type;
83 };
84 
85 template <>
86 struct map_tuple_to_cons<null_type, null_type, null_type, null_type>
87 {
88   typedef null_type type;
89 };
90 
91 class tuple :
92   public map_tuple_to_cons<int, int, int, int>::type
93 {
94 public:
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 
105 void 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 
110 int tailcalled_t1;
111 int tailcalled_t2;
112 int tailcalled_t3;
113 int tailcalled_t4;
114 
115 void 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 
123 int 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