[Gmp-commit] /var/hg/gmp: Initial C++11 support.
mercurial at gmplib.org
mercurial at gmplib.org
Mon Jan 30 23:59:52 CET 2012
details: /var/hg/gmp/rev/d7351c2ba64c
changeset: 14592:d7351c2ba64c
user: Marc Glisse <marc.glisse at inria.fr>
date: Mon Jan 30 23:59:39 2012 +0100
description:
Initial C++11 support.
diffstat:
ChangeLog | 11 +++
gmpxx.h | 51 ++++++++++++++++--
tests/cxx/Makefile.am | 6 +-
tests/cxx/t-cxx11.cc | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 199 insertions(+), 8 deletions(-)
diffs (truncated from 320 to 300 lines):
diff -r 2b74427c67b0 -r d7351c2ba64c ChangeLog
--- a/ChangeLog Mon Jan 30 16:30:26 2012 +0100
+++ b/ChangeLog Mon Jan 30 23:59:39 2012 +0100
@@ -1,3 +1,14 @@
+2012-02-01 Marc Glisse <marc.glisse at 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 at gmplib.org>
* tests/mpz/t-powm.c: Ensure all sizes are seen.
diff -r 2b74427c67b0 -r d7351c2ba64c gmpxx.h
--- a/gmpxx.h Mon Jan 30 16:30:26 2012 +0100
+++ b/gmpxx.h Mon Jan 30 23:59:39 2012 +0100
@@ -48,6 +48,18 @@
#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 @@
__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 @@
~__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 @@
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 @@
~__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 @@
__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 @@
~__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 @@
__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 @@
__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_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 -r 2b74427c67b0 -r d7351c2ba64c tests/cxx/Makefile.am
--- a/tests/cxx/Makefile.am Mon Jan 30 16:30:26 2012 +0100
+++ b/tests/cxx/Makefile.am Mon Jan 30 23:59:39 2012 +0100
@@ -30,8 +30,9 @@
$(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_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 -r 2b74427c67b0 -r d7351c2ba64c tests/cxx/t-cxx11.cc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/cxx/t-cxx11.cc Mon Jan 30 23:59:39 2012 +0100
@@ -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)
+{
More information about the gmp-commit
mailing list