xref: /netbsd-src/external/lgpl3/gmp/dist/tests/cxx/t-cxx11.cc (revision 6d322f2f4598f0d8a138f10ea648ec4fabe41f8b)
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 http://www.gnu.org/licenses/.  */
19 
20 #include "config.h"
21 
22 #include "gmp.h"
23 #include "gmpxx.h"
24 #include "gmp-impl.h"
25 #include "tests.h"
26 
27 #if __GMPXX_USE_CXX11
28 
29 #include <utility>
30 #include <type_traits>
31 
32 void check_noexcept ()
33 {
34   mpz_class z1, z2;
35   mpq_class q1, q2;
36   mpf_class f1, f2;
37   static_assert(noexcept(z1 = std::move(z2)), "sorry");
38   static_assert(noexcept(q1 = std::move(q2)), "sorry");
39   static_assert(noexcept(f1 = std::move(f2)), "sorry");
40   static_assert(noexcept(q1 = std::move(z1)), "sorry");
41 }
42 
43 void check_common_type ()
44 {
45 #define CHECK_COMMON_TYPE(T, U, Res) \
46   static_assert(std::is_same<std::common_type<T, U>::type, Res>::value, "sorry")
47 #define CHECK_COMMON_TYPE_BUILTIN1(T, Res) \
48   CHECK_COMMON_TYPE(  signed char , T, Res); \
49   CHECK_COMMON_TYPE(unsigned char , T, Res); \
50   CHECK_COMMON_TYPE(  signed short, T, Res); \
51   CHECK_COMMON_TYPE(unsigned short, T, Res); \
52   CHECK_COMMON_TYPE(  signed int  , T, Res); \
53   CHECK_COMMON_TYPE(unsigned int  , T, Res); \
54   CHECK_COMMON_TYPE(  signed long , T, Res); \
55   CHECK_COMMON_TYPE(unsigned long , T, Res); \
56   CHECK_COMMON_TYPE(float , T, Res); \
57   CHECK_COMMON_TYPE(double, T, Res)
58 #define CHECK_COMMON_TYPE_BUILTIN2(T, Res) \
59   CHECK_COMMON_TYPE(T,   signed char , Res); \
60   CHECK_COMMON_TYPE(T, unsigned char , Res); \
61   CHECK_COMMON_TYPE(T,   signed short, Res); \
62   CHECK_COMMON_TYPE(T, unsigned short, Res); \
63   CHECK_COMMON_TYPE(T,   signed int  , Res); \
64   CHECK_COMMON_TYPE(T, unsigned int  , Res); \
65   CHECK_COMMON_TYPE(T,   signed long , Res); \
66   CHECK_COMMON_TYPE(T, unsigned long , Res); \
67   CHECK_COMMON_TYPE(T, float , Res); \
68   CHECK_COMMON_TYPE(T, double, Res)
69 #define CHECK_COMMON_TYPE_BUILTIN(T, Res) \
70   CHECK_COMMON_TYPE_BUILTIN1(T, Res); \
71   CHECK_COMMON_TYPE_BUILTIN2(T, Res)
72   /* These would just work with implicit conversions */
73   CHECK_COMMON_TYPE (mpz_class, mpq_class, mpq_class);
74   CHECK_COMMON_TYPE (mpz_class, mpf_class, mpf_class);
75   CHECK_COMMON_TYPE (mpf_class, mpq_class, mpf_class);
76 
77   CHECK_COMMON_TYPE_BUILTIN (mpz_class, mpz_class);
78   CHECK_COMMON_TYPE_BUILTIN (mpq_class, mpq_class);
79   CHECK_COMMON_TYPE_BUILTIN (mpf_class, mpf_class);
80 
81   mpz_class z; mpq_class q; mpf_class f;
82 
83   CHECK_COMMON_TYPE (decltype(-z), mpz_class, mpz_class);
84   CHECK_COMMON_TYPE (decltype(-q), mpq_class, mpq_class);
85   CHECK_COMMON_TYPE (decltype(-f), mpf_class, mpf_class);
86 
87   CHECK_COMMON_TYPE (decltype(-z), mpq_class, mpq_class);
88   CHECK_COMMON_TYPE (decltype(-z), mpf_class, mpf_class);
89   CHECK_COMMON_TYPE (decltype(-q), mpf_class, mpf_class);
90 
91   /* These require a common_type specialization */
92   CHECK_COMMON_TYPE (decltype(-z), decltype(z+z), mpz_class);
93   CHECK_COMMON_TYPE (decltype(-q), decltype(q+q), mpq_class);
94   CHECK_COMMON_TYPE (decltype(-f), decltype(f+f), mpf_class);
95 
96   CHECK_COMMON_TYPE (decltype(-q), mpz_class, mpq_class);
97   CHECK_COMMON_TYPE (decltype(-f), mpz_class, mpf_class);
98   CHECK_COMMON_TYPE (decltype(-f), mpq_class, mpf_class);
99 
100   CHECK_COMMON_TYPE (decltype(-z), decltype(-q), mpq_class);
101   CHECK_COMMON_TYPE (decltype(-z), decltype(-f), mpf_class);
102   CHECK_COMMON_TYPE (decltype(-q), decltype(-f), mpf_class);
103 
104   /* These could be broken by a naive common_type specialization */
105   CHECK_COMMON_TYPE (decltype(-z), decltype(-z), decltype(-z));
106   CHECK_COMMON_TYPE (decltype(-q), decltype(-q), decltype(-q));
107   CHECK_COMMON_TYPE (decltype(-f), decltype(-f), decltype(-f));
108 
109   /* Painful */
110   CHECK_COMMON_TYPE_BUILTIN (decltype(-z), mpz_class);
111   CHECK_COMMON_TYPE_BUILTIN (decltype(-q), mpq_class);
112   CHECK_COMMON_TYPE_BUILTIN (decltype(-f), mpf_class);
113 }
114 
115 template<class T, class U = T>
116 void check_move_init ()
117 {
118   {
119     // Delete moved-from x1
120     T x1 = 3;
121     U x2 = std::move(x1);
122     ASSERT_ALWAYS (x2 == 3);
123   }
124   {
125     // Assign to moved-from x1
126     T x1 = 2;
127     U x2 = std::move(x1);
128     x1 = -7;
129     ASSERT_ALWAYS (x1 == -7);
130     ASSERT_ALWAYS (x2 == 2);
131   }
132 }
133 
134 template<class T, class U = T>
135 void check_move_assign ()
136 {
137   {
138     // Delete moved-from x1
139     T x1 = 3; U x2;
140     x2 = std::move(x1);
141     ASSERT_ALWAYS (x2 == 3);
142   }
143   {
144     // Assign to moved-from x1
145     T x1 = 2; U x2;
146     x2 = std::move(x1);
147     x1 = -7;
148     ASSERT_ALWAYS (x1 == -7);
149     ASSERT_ALWAYS (x2 == 2);
150   }
151   {
152     // Self move-assign (not necessary, but it happens to work...)
153     T x = 4;
154     x = std::move(x);
155     ASSERT_ALWAYS (x == 4);
156   }
157 }
158 
159 void check_user_defined_literal ()
160 {
161   ASSERT_ALWAYS (123_mpz % 5 == 3);
162   ASSERT_ALWAYS (-11_mpq / 22 == -.5);
163   ASSERT_ALWAYS (112.5e-1_mpf * 4 == 45);
164   {
165     mpz_class ref ( "123456789abcdef0123456789abcdef0123", 16);
166     ASSERT_ALWAYS (0x123456789abcdef0123456789abcdef0123_mpz == ref);
167   }
168 }
169 
170 // Check for explicit conversion to bool
171 void implicit_bool(bool);
172 int implicit_bool(...);
173 
174 void check_bool_conversion ()
175 {
176   const mpz_class zn = -2;
177   const mpq_class qn = -2;
178   const mpf_class fn = -2;
179   const mpz_class z0 =  0;
180   const mpq_class q0 =  0;
181   const mpf_class f0 =  0;
182   const mpz_class zp = +2;
183   const mpq_class qp = +2;
184   const mpf_class fp = +2;
185   if (zn && qn && fn && zp && qp && fp && !z0 && !q0 && !f0)
186     {
187       if (z0 || q0 || f0) ASSERT_ALWAYS(false);
188     }
189   else ASSERT_ALWAYS(false);
190   decltype(implicit_bool(zn)) zi = 1;
191   decltype(implicit_bool(qn)) qi = 1;
192   decltype(implicit_bool(fn)) fi = 1;
193   (void)(zi+qi+fi);
194 }
195 
196 int
197 main (void)
198 {
199   tests_start();
200 
201   check_noexcept();
202   check_common_type();
203   check_move_init<mpz_class>();
204   check_move_init<mpq_class>();
205   check_move_init<mpf_class>();
206   check_move_assign<mpz_class>();
207   check_move_assign<mpq_class>();
208   check_move_assign<mpf_class>();
209   check_move_init<mpz_class,mpq_class>();
210   check_move_assign<mpz_class,mpq_class>();
211   check_user_defined_literal();
212   check_bool_conversion();
213 
214   tests_end();
215   return 0;
216 }
217 
218 #else
219 int main () { return 0; }
220 #endif
221