xref: /netbsd-src/external/lgpl3/gmp/dist/tests/cxx/t-cxx11.cc (revision 72c7faa4dbb41dbb0238d6b4a109da0d4b236dd4)
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