1 /* Test C++11 features
2
3 Copyright 2011, 2012 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library test suite.
6
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 Public License for more details.
16
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
19
20 #include "config.h"
21
22 #include "gmpxx.h"
23 #include "gmp-impl.h"
24 #include "tests.h"
25
26 #if __GMPXX_USE_CXX11
27
28 #include <utility>
29 #include <type_traits>
30
check_noexcept()31 void check_noexcept ()
32 {
33 mpz_class z1, z2;
34 mpq_class q1, q2;
35 mpf_class f1, f2;
36 static_assert(noexcept(z1 = std::move(z2)), "sorry");
37 static_assert(noexcept(q1 = std::move(q2)), "sorry");
38 static_assert(noexcept(f1 = std::move(f2)), "sorry");
39 static_assert(noexcept(q1 = std::move(z1)), "sorry");
40
41 // Only mpz has lazy allocation for now
42 static_assert(std::is_nothrow_default_constructible<mpz_class>::value, "sorry");
43 static_assert(std::is_nothrow_move_constructible<mpz_class>::value, "sorry");
44 static_assert(!std::is_nothrow_default_constructible<mpq_class>::value, "sorry");
45 static_assert(!std::is_nothrow_move_constructible<mpq_class>::value, "sorry");
46 static_assert(!std::is_nothrow_default_constructible<mpf_class>::value, "sorry");
47 static_assert(!std::is_nothrow_move_constructible<mpf_class>::value, "sorry");
48 }
49
check_common_type()50 void check_common_type ()
51 {
52 #define CHECK_COMMON_TYPE1(T, Res) \
53 static_assert(std::is_same<std::common_type<T>::type, Res>::value, "sorry")
54 #define CHECK_COMMON_TYPE(T, U, Res) \
55 static_assert(std::is_same<std::common_type<T, U>::type, Res>::value, "sorry")
56 #define CHECK_COMMON_TYPE_BUILTIN1(T, Res) \
57 CHECK_COMMON_TYPE( signed char , T, Res); \
58 CHECK_COMMON_TYPE(unsigned char , T, Res); \
59 CHECK_COMMON_TYPE( signed short, T, Res); \
60 CHECK_COMMON_TYPE(unsigned short, T, Res); \
61 CHECK_COMMON_TYPE( signed int , T, Res); \
62 CHECK_COMMON_TYPE(unsigned int , T, Res); \
63 CHECK_COMMON_TYPE( signed long , T, Res); \
64 CHECK_COMMON_TYPE(unsigned long , T, Res); \
65 CHECK_COMMON_TYPE(float , T, Res); \
66 CHECK_COMMON_TYPE(double, T, Res)
67 #define CHECK_COMMON_TYPE_BUILTIN2(T, Res) \
68 CHECK_COMMON_TYPE(T, signed char , Res); \
69 CHECK_COMMON_TYPE(T, unsigned char , Res); \
70 CHECK_COMMON_TYPE(T, signed short, Res); \
71 CHECK_COMMON_TYPE(T, unsigned short, Res); \
72 CHECK_COMMON_TYPE(T, signed int , Res); \
73 CHECK_COMMON_TYPE(T, unsigned int , Res); \
74 CHECK_COMMON_TYPE(T, signed long , Res); \
75 CHECK_COMMON_TYPE(T, unsigned long , Res); \
76 CHECK_COMMON_TYPE(T, float , Res); \
77 CHECK_COMMON_TYPE(T, double, Res)
78 #define CHECK_COMMON_TYPE_BUILTIN(T, Res) \
79 CHECK_COMMON_TYPE_BUILTIN1(T, Res); \
80 CHECK_COMMON_TYPE_BUILTIN2(T, Res)
81 /* These would just work with implicit conversions */
82 CHECK_COMMON_TYPE (mpz_class, mpq_class, mpq_class);
83 CHECK_COMMON_TYPE (mpz_class, mpf_class, mpf_class);
84 CHECK_COMMON_TYPE (mpf_class, mpq_class, mpf_class);
85
86 CHECK_COMMON_TYPE_BUILTIN (mpz_class, mpz_class);
87 CHECK_COMMON_TYPE_BUILTIN (mpq_class, mpq_class);
88 CHECK_COMMON_TYPE_BUILTIN (mpf_class, mpf_class);
89
90 mpz_class z; mpq_class q; mpf_class f;
91
92 CHECK_COMMON_TYPE (decltype(-z), mpz_class, mpz_class);
93 CHECK_COMMON_TYPE (decltype(-q), mpq_class, mpq_class);
94 CHECK_COMMON_TYPE (decltype(-f), mpf_class, mpf_class);
95
96 CHECK_COMMON_TYPE (decltype(-z), mpq_class, mpq_class);
97 CHECK_COMMON_TYPE (decltype(-z), mpf_class, mpf_class);
98 CHECK_COMMON_TYPE (decltype(-q), mpf_class, mpf_class);
99
100 /* These require a common_type specialization */
101 CHECK_COMMON_TYPE (decltype(-z), decltype(z+z), mpz_class);
102 CHECK_COMMON_TYPE (decltype(-q), decltype(q+q), mpq_class);
103 CHECK_COMMON_TYPE (decltype(-f), decltype(f+f), mpf_class);
104
105 CHECK_COMMON_TYPE (decltype(-q), mpz_class, mpq_class);
106 CHECK_COMMON_TYPE (decltype(-f), mpz_class, mpf_class);
107 CHECK_COMMON_TYPE (decltype(-f), mpq_class, mpf_class);
108
109 CHECK_COMMON_TYPE (decltype(-z), decltype(-q), mpq_class);
110 CHECK_COMMON_TYPE (decltype(-z), decltype(-f), mpf_class);
111 CHECK_COMMON_TYPE (decltype(-q), decltype(-f), mpf_class);
112
113 /* common_type now decays */
114 CHECK_COMMON_TYPE (decltype(-z), decltype(-z), mpz_class);
115 CHECK_COMMON_TYPE (decltype(-q), decltype(-q), mpq_class);
116 CHECK_COMMON_TYPE (decltype(-f), decltype(-f), mpf_class);
117 CHECK_COMMON_TYPE1 (decltype(-z), mpz_class);
118 CHECK_COMMON_TYPE1 (decltype(-q), mpq_class);
119 CHECK_COMMON_TYPE1 (decltype(-f), mpf_class);
120
121 /* Painful */
122 CHECK_COMMON_TYPE_BUILTIN (decltype(-z), mpz_class);
123 CHECK_COMMON_TYPE_BUILTIN (decltype(-q), mpq_class);
124 CHECK_COMMON_TYPE_BUILTIN (decltype(-f), mpf_class);
125 }
126
127 template<class T, class U = T>
check_move_init()128 void check_move_init ()
129 {
130 {
131 // Delete moved-from x1
132 T x1 = 3;
133 U x2 = std::move(x1);
134 ASSERT_ALWAYS (x2 == 3);
135 }
136 {
137 // Assign to moved-from x1
138 T x1 = 2;
139 U x2 = std::move(x1);
140 x1 = -7;
141 ASSERT_ALWAYS (x1 == -7);
142 ASSERT_ALWAYS (x2 == 2);
143 }
144 }
145
146 template<class T, class U = T>
check_move_assign()147 void check_move_assign ()
148 {
149 {
150 // Delete moved-from x1
151 T x1 = 3; U x2;
152 x2 = std::move(x1);
153 ASSERT_ALWAYS (x2 == 3);
154 }
155 {
156 // Assign to moved-from x1
157 T x1 = 2; U x2;
158 x2 = std::move(x1);
159 x1 = -7;
160 ASSERT_ALWAYS (x1 == -7);
161 ASSERT_ALWAYS (x2 == 2);
162 }
163 {
164 // Self move-assign (not necessary, but it happens to work...)
165 T x = 4;
166 x = std::move(x);
167 ASSERT_ALWAYS (x == 4);
168 }
169 }
170
check_user_defined_literal()171 void check_user_defined_literal ()
172 {
173 ASSERT_ALWAYS (123_mpz % 5 == 3);
174 ASSERT_ALWAYS (-11_mpq / 22 == -.5);
175 ASSERT_ALWAYS (112.5e-1_mpf * 4 == 45);
176 {
177 mpz_class ref ( "123456789abcdef0123456789abcdef0123", 16);
178 ASSERT_ALWAYS (0x123456789abcdef0123456789abcdef0123_mpz == ref);
179 }
180 }
181
182 // Check for explicit conversion to bool
183 void implicit_bool(bool);
184 int implicit_bool(...);
185
check_bool_conversion()186 void check_bool_conversion ()
187 {
188 const mpz_class zn = -2;
189 const mpq_class qn = -2;
190 const mpf_class fn = -2;
191 const mpz_class z0 = 0;
192 const mpq_class q0 = 0;
193 const mpf_class f0 = 0;
194 const mpz_class zp = +2;
195 const mpq_class qp = +2;
196 const mpf_class fp = +2;
197 if (zn && qn && fn && zp && qp && fp && !z0 && !q0 && !f0)
198 {
199 if (z0 || q0 || f0) ASSERT_ALWAYS(false);
200 }
201 else ASSERT_ALWAYS(false);
202 decltype(implicit_bool(zn)) zi = 1;
203 decltype(implicit_bool(qn)) qi = 1;
204 decltype(implicit_bool(fn)) fi = 1;
205 (void)(zi+qi+fi);
206 }
207
208 int
main(void)209 main (void)
210 {
211 tests_start();
212
213 check_noexcept();
214 check_common_type();
215 check_move_init<mpz_class>();
216 check_move_init<mpq_class>();
217 check_move_init<mpf_class>();
218 check_move_assign<mpz_class>();
219 check_move_assign<mpq_class>();
220 check_move_assign<mpf_class>();
221 check_move_init<mpz_class,mpq_class>();
222 check_move_assign<mpz_class,mpq_class>();
223 check_user_defined_literal();
224 check_bool_conversion();
225
226 tests_end();
227 return 0;
228 }
229
230 #else
main()231 int main () { return 0; }
232 #endif
233