summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2012-01-30 23:59:39 +0100
committerMarc Glisse <marc.glisse@inria.fr>2012-01-30 23:59:39 +0100
commita423d2db41e026280cd883e31a20975fa814cb7e (patch)
treea4f574758ec3c64c0df39e5a3684fb72b0e9d385
parent8d49dafc7c996ee3cb08195521e7b8bc49a90b7d (diff)
downloadgmp-a423d2db41e026280cd883e31a20975fa814cb7e.tar.gz
Initial C++11 support.
-rw-r--r--ChangeLog11
-rw-r--r--gmpxx.h51
-rw-r--r--tests/cxx/Makefile.am6
-rw-r--r--tests/cxx/t-cxx11.cc139
4 files changed, 199 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 013a3eb6f..1e41f9a65 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2012-02-01 Marc Glisse <marc.glisse@inria.fr>
+
+ * gmpxx.h (__gmp_unary_expr): Make the constructor explicit.
+ (__gmp_expr(__gmp_expr&&)): New move constructors.
+ (__gmp_expr::operator=(__gmp_expr&&)): New move assignments.
+ (swap): Mark as noexcept.
+ (__GMPXX_USE_CXX11): New macro.
+ (__GMPXX_NOEXCEPT): New macro.
+ * tests/cxx/t-cxx11.cc: New file.
+ * tests/cxx/Makefile.am: Added t-cxx11.
+
2012-01-30 Torbjorn Granlund <tege@gmplib.org>
* tests/mpz/t-powm.c: Ensure all sizes are seen.
diff --git a/gmpxx.h b/gmpxx.h
index c629e14fa..16d90a44f 100644
--- a/gmpxx.h
+++ b/gmpxx.h
@@ -48,6 +48,18 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
#define __GMPXX_CONSTANT(X) false
#endif
+// Use C++11 features
+#ifndef __GMPXX_USE_CXX11
+#if (__cplusplus >= 201103L) \
+ || (__GMP_GNUC_PREREQ(4, 6) && defined __GXX_EXPERIMENTAL_CXX0X__)
+#define __GMPXX_USE_CXX11 1
+#define __GMPXX_NOEXCEPT noexcept
+#else
+#define __GMPXX_USE_CXX11 0
+#define __GMPXX_NOEXCEPT
+#endif
+#endif
+
// Max allocations for plain types when converted to mpz_t
#define __GMPZ_DBL_LIMBS (2 + DBL_MAX_EXP / GMP_NUMB_BITS)
@@ -1412,6 +1424,10 @@ public:
__gmp_expr() { mpz_init(mp); }
__gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); }
+#if __GMPXX_USE_CXX11
+ __gmp_expr(__gmp_expr &&z)
+ { *mp = *z.mp; mpz_init(z.mp); }
+#endif
template <class T>
__gmp_expr(const __gmp_expr<mpz_t, T> &expr)
{ mpz_init(mp); __gmp_set_expr(mp, expr); }
@@ -1456,11 +1472,15 @@ public:
~__gmp_expr() { mpz_clear(mp); }
- void swap(__gmp_expr& z) { std::swap(*mp, *z.mp); }
+ void swap(__gmp_expr& z) __GMPXX_NOEXCEPT { std::swap(*mp, *z.mp); }
// assignment operators
__gmp_expr & operator=(const __gmp_expr &z)
{ mpz_set(mp, z.mp); return *this; }
+#if __GMPXX_USE_CXX11
+ __gmp_expr & operator=(__gmp_expr &&z) noexcept
+ { swap(z); return *this; }
+#endif
template <class T, class U>
__gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
{ __gmp_set_expr(mp, expr); return *this; }
@@ -1573,6 +1593,10 @@ public:
mpz_init_set(mpq_numref(mp), mpq_numref(q.mp));
mpz_init_set(mpq_denref(mp), mpq_denref(q.mp));
}
+#if __GMPXX_USE_CXX11
+ __gmp_expr(__gmp_expr &&q)
+ { *mp = *q.mp; mpq_init(q.mp); }
+#endif
template <class T>
__gmp_expr(const __gmp_expr<mpz_t, T> &expr)
{ mpq_init(mp); __gmp_set_expr(mp, expr); }
@@ -1631,11 +1655,17 @@ public:
~__gmp_expr() { mpq_clear(mp); }
- void swap(__gmp_expr& q) { std::swap(*mp, *q.mp); }
+ void swap(__gmp_expr& q) __GMPXX_NOEXCEPT { std::swap(*mp, *q.mp); }
// assignment operators
__gmp_expr & operator=(const __gmp_expr &q)
{ mpq_set(mp, q.mp); return *this; }
+#if __GMPXX_USE_CXX11
+ __gmp_expr & operator=(__gmp_expr &&q) noexcept
+ { swap(q); return *this; }
+ __gmp_expr & operator=(mpz_class &&z) noexcept
+ { get_num() = std::move(z); get_den() = 1u; return *this; }
+#endif
template <class T, class U>
__gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
{ __gmp_set_expr(mp, expr); return *this; }
@@ -1749,6 +1779,10 @@ public:
__gmp_expr(const __gmp_expr &f)
{ mpf_init2(mp, f.get_prec()); mpf_set(mp, f.mp); }
+#if __GMPXX_USE_CXX11
+ __gmp_expr(__gmp_expr &&f)
+ { *mp = *f.mp; mpf_init2(f.mp, get_prec()); }
+#endif
__gmp_expr(const __gmp_expr &f, mp_bitcnt_t prec)
{ mpf_init2(mp, prec); mpf_set(mp, f.mp); }
template <class T, class U>
@@ -1838,11 +1872,15 @@ public:
~__gmp_expr() { mpf_clear(mp); }
- void swap(__gmp_expr& f) { std::swap(*mp, *f.mp); }
+ void swap(__gmp_expr& f) __GMPXX_NOEXCEPT { std::swap(*mp, *f.mp); }
// assignment operators
__gmp_expr & operator=(const __gmp_expr &f)
{ mpf_set(mp, f.mp); return *this; }
+#if __GMPXX_USE_CXX11
+ __gmp_expr & operator=(__gmp_expr &&f) noexcept
+ { swap(f); return *this; }
+#endif
template <class T, class U>
__gmp_expr<value_type, value_type> & operator=(const __gmp_expr<T, U> &expr)
{ __gmp_set_expr(mp, expr); return *this; }
@@ -2065,7 +2103,7 @@ private:
__gmp_unary_expr<val_type, Op> expr;
public:
- __gmp_expr(const val_type &val) : expr(val) { }
+ explicit __gmp_expr(const val_type &val) : expr(val) { }
void eval(typename __gmp_resolve_expr<T>::ptr_type p,
mp_bitcnt_t = 0) const
{ Op::eval(p, expr.val.__get_mp()); }
@@ -2084,7 +2122,7 @@ private:
__gmp_unary_expr<val_type, Op> expr;
public:
- __gmp_expr(const val_type &val) : expr(val) { }
+ explicit __gmp_expr(const val_type &val) : expr(val) { }
void eval(typename __gmp_resolve_expr<T>::ptr_type p) const
{ expr.val.eval(p); Op::eval(p, p); }
void eval(typename __gmp_resolve_expr<T>::ptr_type p,
@@ -3008,7 +3046,8 @@ __GMP_DEFINE_UNARY_TYPE_FUNCTION(int, sgn, __gmp_sgn_function)
__GMP_DEFINE_BINARY_TYPE_FUNCTION(int, cmp, __gmp_cmp_function)
template <class T>
-void swap(__gmp_expr<T, T>& x, __gmp_expr<T, T>& y) { x.swap(y); }
+void swap(__gmp_expr<T, T>& x, __gmp_expr<T, T>& y) __GMPXX_NOEXCEPT
+{ x.swap(y); }
// member operators for mpz_class
diff --git a/tests/cxx/Makefile.am b/tests/cxx/Makefile.am
index 6e214ab6f..f339519f4 100644
--- a/tests/cxx/Makefile.am
+++ b/tests/cxx/Makefile.am
@@ -30,8 +30,9 @@ LDADD = -L$(top_builddir)/.libs \
$(top_builddir)/libgmp.la
if WANT_CXX
-check_PROGRAMS = t-assign t-binary t-cast t-constr t-headers t-iostream \
- t-istream t-locale t-misc t-mix t-ops t-ops2 t-ops3 t-ostream t-prec \
+check_PROGRAMS = t-assign t-binary t-cast t-constr t-cxx11 \
+ t-headers t-iostream t-istream t-locale t-misc t-mix \
+ t-ops t-ops2 t-ops3 t-ostream t-prec \
t-rand t-ternary t-unary
TESTS = $(check_PROGRAMS)
endif
@@ -40,6 +41,7 @@ t_assign_SOURCES = t-assign.cc
t_binary_SOURCES = t-binary.cc
t_cast_SOURCES = t-cast.cc
t_constr_SOURCES = t-constr.cc
+t_cxx11_SOURCES = t-cxx11.cc
t_headers_SOURCES = t-headers.cc
t_iostream_SOURCES= t-iostream.cc
t_istream_SOURCES = t-istream.cc
diff --git a/tests/cxx/t-cxx11.cc b/tests/cxx/t-cxx11.cc
new file mode 100644
index 000000000..8c4473c03
--- /dev/null
+++ b/tests/cxx/t-cxx11.cc
@@ -0,0 +1,139 @@
+/* Test C++11 features
+
+Copyright 2011 Free Software Foundation, Inc.
+
+This file is part of the GNU MP Library.
+
+The GNU MP Library is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+The GNU MP Library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
+
+#include "config.h"
+
+#include "gmp.h"
+#include "gmpxx.h"
+#include "gmp-impl.h"
+#include "tests.h"
+
+#if __GMPXX_USE_CXX11
+
+#include <utility>
+#include <type_traits>
+
+void check_noexcept ()
+{
+ mpz_class z1, z2;
+ mpq_class q1, q2;
+ mpf_class f1, f2;
+ // gcc 4.6 is missing noexcept on std::move
+ static_assert(noexcept(z1 = static_cast<mpz_class&&>(z2)), "sorry");
+ static_assert(noexcept(q1 = static_cast<mpq_class&&>(q2)), "sorry");
+ static_assert(noexcept(f1 = static_cast<mpf_class&&>(f2)), "sorry");
+ static_assert(noexcept(q1 = static_cast<mpz_class&&>(z1)), "sorry");
+}
+
+void check_common_type ()
+{
+#define CHECK_COMMON_TYPE(T, U, Res) \
+ static_assert(std::is_same<std::common_type<T, U>::type, Res>::value, "sorry")
+ CHECK_COMMON_TYPE (mpz_class, mpq_class, mpq_class);
+ CHECK_COMMON_TYPE (mpz_class, mpf_class, mpf_class);
+ CHECK_COMMON_TYPE (mpf_class, mpq_class, mpf_class);
+
+ mpz_class z; mpq_class q; mpf_class f;
+
+ CHECK_COMMON_TYPE (decltype(-z), mpz_class, mpz_class);
+ CHECK_COMMON_TYPE (decltype(-q), mpq_class, mpq_class);
+ CHECK_COMMON_TYPE (decltype(-f), mpf_class, mpf_class);
+
+ CHECK_COMMON_TYPE (decltype(-z), mpq_class, mpq_class);
+ CHECK_COMMON_TYPE (decltype(-z), mpf_class, mpf_class);
+ CHECK_COMMON_TYPE (decltype(-q), mpf_class, mpf_class);
+
+ /* Not currently supported
+ CHECK_COMMON_TYPE (decltype(-q), mpz_class, mpq_class);
+ CHECK_COMMON_TYPE (decltype(-f), mpz_class, mpf_class);
+ CHECK_COMMON_TYPE (decltype(-f), mpq_class, mpf_class);
+
+ CHECK_COMMON_TYPE (decltype(-z), decltype(-q), mpq_class);
+ CHECK_COMMON_TYPE (decltype(-z), decltype(-f), mpq_class);
+ CHECK_COMMON_TYPE (decltype(-q), decltype(-f), mpq_class);
+ */
+}
+
+template<class T, class U = T>
+void check_move_init ()
+{
+ {
+ // Delete moved-from x1
+ T x1 = 3;
+ U x2 = std::move(x1);
+ ASSERT_ALWAYS (x2 == 3);
+ }
+ {
+ // Assign to moved-from x1
+ T x1 = 2;
+ U x2 = std::move(x1);
+ x1 = -7;
+ ASSERT_ALWAYS (x1 == -7);
+ ASSERT_ALWAYS (x2 == 2);
+ }
+}
+
+template<class T, class U = T>
+void check_move_assign ()
+{
+ {
+ // Delete moved-from x1
+ T x1 = 3; U x2;
+ x2 = std::move(x1);
+ ASSERT_ALWAYS (x2 == 3);
+ }
+ {
+ // Assign to moved-from x1
+ T x1 = 2; U x2;
+ x2 = std::move(x1);
+ x1 = -7;
+ ASSERT_ALWAYS (x1 == -7);
+ ASSERT_ALWAYS (x2 == 2);
+ }
+ {
+ // Self move-assign (not necessary, but it happens to work...)
+ T x = 4;
+ x = std::move(x);
+ ASSERT_ALWAYS (x == 4);
+ }
+}
+
+int
+main (void)
+{
+ tests_start();
+
+ check_noexcept();
+ check_common_type();
+ check_move_init<mpz_class>();
+ check_move_init<mpq_class>();
+ check_move_init<mpf_class>();
+ check_move_assign<mpz_class>();
+ check_move_assign<mpq_class>();
+ check_move_assign<mpf_class>();
+ check_move_init<mpz_class,mpq_class>();
+ check_move_assign<mpz_class,mpq_class>();
+
+ tests_end();
+ return 0;
+}
+
+#else
+int main () { return 0; }
+#endif