blob: 8d6fccbfeb346d39cc23cea15e96175f2d756649 [file] [log] [blame]
Austin Schuhdace2a62020-08-18 10:56:48 -07001/* Test C++11 features
2
3Copyright 2011, 2012 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library test suite.
6
7The GNU MP Library test suite is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 3 of the License,
10or (at your option) any later version.
11
12The GNU MP Library test suite is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15Public License for more details.
16
17You should have received a copy of the GNU General Public License along with
18the 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
31void 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
50void 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
127template<class T, class U = T>
128void 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
146template<class T, class U = T>
147void 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
171void 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
183void implicit_bool(bool);
184int implicit_bool(...);
185
186void 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
208int
209main (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
231int main () { return 0; }
232#endif