1// I, Howard Hinnant, hereby place this code in the public domain.
2
3// Test the reference collapsing rules.  Note that there are recent differences
4//    for how cv-qualifications are applied to reference types. 7.1.3, 14.3.1
5
6// { dg-do compile { target c++11 } }
7
8template <bool> struct sa;
9template <> struct sa<true> {};
10
11template <class T, T v>
12struct integral_constant
13{
14	static const T                  value = v;
15	typedef T                       value_type;
16	typedef integral_constant<T, v> type;
17};
18
19typedef integral_constant<bool, true>  true_type;
20typedef integral_constant<bool, false> false_type;
21
22template <class T> struct is_lvalue_reference     : public integral_constant<bool, false> {};
23template <class T> struct is_lvalue_reference<T&> : public integral_constant<bool, true> {};
24
25template <class T> struct is_rvalue_reference      : public integral_constant<bool, false> {};
26template <class T> struct is_rvalue_reference<T&&> : public integral_constant<bool, true> {};
27
28template <class T> struct remove_reference      {typedef T type;};
29template <class T> struct remove_reference<T&>  {typedef T type;};
30template <class T> struct remove_reference<T&&> {typedef T type;};
31
32template <class T> struct is_const          : public integral_constant<bool, false> {};
33template <class T> struct is_const<T const> : public integral_constant<bool, true> {};
34
35template <class T> struct is_volatile             : public integral_constant<bool, false> {};
36template <class T> struct is_volatile<T volatile> : public integral_constant<bool, true> {};
37
38struct A {};
39
40typedef A& Alref;
41typedef const A& cAlref;
42typedef volatile A& vAlref;
43typedef const volatile A& cvAlref;
44
45typedef A&& Arref;
46typedef const A&& cArref;
47typedef volatile A&& vArref;
48typedef const volatile A&& cvArref;
49
50template <class T, bool is_lvalue_ref, bool is_rvalue_ref, bool s_const, bool s_volatile>
51void test()
52{
53    sa<is_lvalue_reference<T>::value == is_lvalue_ref> t1;
54    sa<is_rvalue_reference<T>::value == is_rvalue_ref> t2;
55    sa<is_const   <typename remove_reference<T>::type>::value == s_const>    t3;
56    sa<is_volatile<typename remove_reference<T>::type>::value == s_volatile> t4;
57    sa<is_const   <typename remove_reference<const          T>::type>::value == s_const   > t5;
58    sa<is_volatile<typename remove_reference<      volatile T>::type>::value == s_volatile> t6;
59}
60
61int main()
62{
63    // sanity check
64    test<               A&,   true, false, false, false>();
65    test<const          A&,   true, false,  true, false>();
66    test<      volatile A&,   true, false, false,  true>();
67    test<const volatile A&,   true, false,  true,  true>();
68    test<               A&&, false,  true, false, false>();
69    test<const          A&&, false,  true,  true, false>();
70    test<      volatile A&&, false,  true, false,  true>();
71    test<const volatile A&&, false,  true,  true,  true>();
72
73// lvalue reference test
74
75    // Alref
76    test<               Alref&,  true, false, false, false>();
77    test<const          Alref&,  true, false, false, false>();
78    test<      volatile Alref&,  true, false, false, false>();
79    test<const volatile Alref&,  true, false, false, false>();
80
81    // cAlref
82    test<               cAlref&,  true, false,  true, false>();
83    test<const          cAlref&,  true, false,  true, false>();
84    test<      volatile cAlref&,  true, false,  true, false>();
85    test<const volatile cAlref&,  true, false,  true, false>();
86
87    // vAlref
88    test<               vAlref&,  true, false, false,  true>();
89    test<const          vAlref&,  true, false, false,  true>();
90    test<      volatile vAlref&,  true, false, false,  true>();
91    test<const volatile vAlref&,  true, false, false,  true>();
92
93    // cvAlref
94    test<               cvAlref&,  true, false,  true,  true>();
95    test<const          cvAlref&,  true, false,  true,  true>();
96    test<      volatile cvAlref&,  true, false,  true,  true>();
97    test<const volatile cvAlref&,  true, false,  true,  true>();
98
99    // Arref
100    test<               Arref&,  true, false, false, false>();
101    test<const          Arref&,  true, false, false, false>();
102    test<      volatile Arref&,  true, false, false, false>();
103    test<const volatile Arref&,  true, false, false, false>();
104
105    // cArref
106    test<               cArref&,  true, false,  true, false>();
107    test<const          cArref&,  true, false,  true, false>();
108    test<      volatile cArref&,  true, false,  true, false>();
109    test<const volatile cArref&,  true, false,  true, false>();
110
111    // vArref
112    test<               vArref&,  true, false, false,  true>();
113    test<const          vArref&,  true, false, false,  true>();
114    test<      volatile vArref&,  true, false, false,  true>();
115    test<const volatile vArref&,  true, false, false,  true>();
116
117    // vArref
118    test<               cvArref&,  true, false,  true,  true>();
119    test<const          cvArref&,  true, false,  true,  true>();
120    test<      volatile cvArref&,  true, false,  true,  true>();
121    test<const volatile cvArref&,  true, false,  true,  true>();
122
123// rvalue reference test
124
125    // Alref
126    test<               Alref&&,  true, false, false, false>();
127    test<const          Alref&&,  true, false, false, false>();
128    test<      volatile Alref&&,  true, false, false, false>();
129    test<const volatile Alref&&,  true, false, false, false>();
130
131    // cAlref
132    test<               cAlref&&,  true, false,  true, false>();
133    test<const          cAlref&&,  true, false,  true, false>();
134    test<      volatile cAlref&&,  true, false,  true, false>();
135    test<const volatile cAlref&&,  true, false,  true, false>();
136
137    // vAlref
138    test<               vAlref&&,  true, false, false,  true>();
139    test<const          vAlref&&,  true, false, false,  true>();
140    test<      volatile vAlref&&,  true, false, false,  true>();
141    test<const volatile vAlref&&,  true, false, false,  true>();
142
143    // cvAlref
144    test<               cvAlref&&,  true, false,  true,  true>();
145    test<const          cvAlref&&,  true, false,  true,  true>();
146    test<      volatile cvAlref&&,  true, false,  true,  true>();
147    test<const volatile cvAlref&&,  true, false,  true,  true>();
148
149    // Arref
150    test<               Arref&&, false,  true, false, false>();
151    test<const          Arref&&, false,  true, false, false>();
152    test<      volatile Arref&&, false,  true, false, false>();
153    test<const volatile Arref&&, false,  true, false, false>();
154
155    // cArref
156    test<               cArref&&, false,  true,  true, false>();
157    test<const          cArref&&, false,  true,  true, false>();
158    test<      volatile cArref&&, false,  true,  true, false>();
159    test<const volatile cArref&&, false,  true,  true, false>();
160
161    // vArref
162    test<               vArref&&, false,  true, false,  true>();
163    test<const          vArref&&, false,  true, false,  true>();
164    test<      volatile vArref&&, false,  true, false,  true>();
165    test<const volatile vArref&&, false,  true, false,  true>();
166
167    // cvArref
168    test<               cvArref&&, false,  true,  true,  true>();
169    test<const          cvArref&&, false,  true,  true,  true>();
170    test<      volatile cvArref&&, false,  true,  true,  true>();
171    test<const volatile cvArref&&, false,  true,  true,  true>();
172
173    return 0;
174}
175