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