1/* 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 233