[Gmp-commit] /var/hg/gmp: Specialize std::common_type in C++11.

mercurial at gmplib.org mercurial at gmplib.org
Sat Feb 18 13:22:24 CET 2012


details:   /var/hg/gmp/rev/4e059a4847ec
changeset: 14641:4e059a4847ec
user:      Marc Glisse <marc.glisse at inria.fr>
date:      Sat Feb 18 13:22:19 2012 +0100
description:
Specialize std::common_type in C++11.

diffstat:

 ChangeLog            |   5 +++++
 gmpxx.h              |  28 +++++++++++++++++++++++++---
 tests/cxx/t-cxx11.cc |  50 +++++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 77 insertions(+), 6 deletions(-)

diffs (137 lines):

diff -r 4bb45d7afdc4 -r 4e059a4847ec ChangeLog
--- a/ChangeLog	Fri Feb 17 21:57:04 2012 +0100
+++ b/ChangeLog	Sat Feb 18 13:22:19 2012 +0100
@@ -1,3 +1,8 @@
+2012-02-18  Marc Glisse  <marc.glisse at inria.fr>
+
+	* gmpxx.h (std::common_type): New partial specialization in C++11.
+	* tests/cxx/t-cxx11.cc: Test it.
+
 2012-02-17  Marc Glisse  <marc.glisse at inria.fr>
 
 	* gmp-h.in (__GMP_WITHIN_GMP): Test with #ifdef instead of #if, for
diff -r 4bb45d7afdc4 -r 4e059a4847ec gmpxx.h
--- a/gmpxx.h	Fri Feb 17 21:57:04 2012 +0100
+++ b/gmpxx.h	Sat Feb 18 13:22:19 2012 +0100
@@ -42,12 +42,17 @@
 #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
+#endif
+#endif
+
+#if __GMPXX_USE_CXX11
+#define __GMPXX_NOEXCEPT noexcept
+#include <type_traits> // for common_type
+#else
 #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)
@@ -1339,7 +1344,24 @@
   typedef mpf_t value_type;
 };
 
-
+#if __GMPXX_USE_CXX11
+namespace std {
+  template <class T, class U, class V, class W>
+  struct common_type <__gmp_expr<T, U>, __gmp_expr<V, W> >
+  {
+  private:
+    typedef typename __gmp_resolve_expr<T, V>::value_type X;
+  public:
+    typedef __gmp_expr<X, X> type;
+  };
+
+  template <class T, class U>
+  struct common_type <__gmp_expr<T, U>, __gmp_expr<T, U> >
+  {
+    typedef __gmp_expr<T, U> type;
+  };
+}
+#endif
 
 // classes for evaluating unary and binary expressions
 template <class T, class Op>
diff -r 4bb45d7afdc4 -r 4e059a4847ec tests/cxx/t-cxx11.cc
--- a/tests/cxx/t-cxx11.cc	Fri Feb 17 21:57:04 2012 +0100
+++ b/tests/cxx/t-cxx11.cc	Sat Feb 18 13:22:19 2012 +0100
@@ -45,10 +45,40 @@
 {
 #define CHECK_COMMON_TYPE(T, U, Res) \
   static_assert(std::is_same<std::common_type<T, U>::type, Res>::value, "sorry")
+#define CHECK_COMMON_TYPE_BUILTIN1(T, Res) \
+  CHECK_COMMON_TYPE(  signed char , T, Res); \
+  CHECK_COMMON_TYPE(unsigned char , T, Res); \
+  CHECK_COMMON_TYPE(  signed short, T, Res); \
+  CHECK_COMMON_TYPE(unsigned short, T, Res); \
+  CHECK_COMMON_TYPE(  signed int  , T, Res); \
+  CHECK_COMMON_TYPE(unsigned int  , T, Res); \
+  CHECK_COMMON_TYPE(  signed long , T, Res); \
+  CHECK_COMMON_TYPE(unsigned long , T, Res); \
+  CHECK_COMMON_TYPE(float , T, Res); \
+  CHECK_COMMON_TYPE(double, T, Res)
+#define CHECK_COMMON_TYPE_BUILTIN2(T, Res) \
+  CHECK_COMMON_TYPE(T,   signed char , Res); \
+  CHECK_COMMON_TYPE(T, unsigned char , Res); \
+  CHECK_COMMON_TYPE(T,   signed short, Res); \
+  CHECK_COMMON_TYPE(T, unsigned short, Res); \
+  CHECK_COMMON_TYPE(T,   signed int  , Res); \
+  CHECK_COMMON_TYPE(T, unsigned int  , Res); \
+  CHECK_COMMON_TYPE(T,   signed long , Res); \
+  CHECK_COMMON_TYPE(T, unsigned long , Res); \
+  CHECK_COMMON_TYPE(T, float , Res); \
+  CHECK_COMMON_TYPE(T, double, Res)
+#define CHECK_COMMON_TYPE_BUILTIN(T, Res) \
+  CHECK_COMMON_TYPE_BUILTIN1(T, Res); \
+  CHECK_COMMON_TYPE_BUILTIN2(T, Res)
+  /* These would just work with implicit conversions */
   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);
 
+  CHECK_COMMON_TYPE_BUILTIN (mpz_class, mpz_class);
+  CHECK_COMMON_TYPE_BUILTIN (mpq_class, mpq_class);
+  CHECK_COMMON_TYPE_BUILTIN (mpf_class, mpf_class);
+
   mpz_class z; mpq_class q; mpf_class f;
 
   CHECK_COMMON_TYPE (decltype(-z), mpz_class, mpz_class);
@@ -59,14 +89,28 @@
   CHECK_COMMON_TYPE (decltype(-z), mpf_class, mpf_class);
   CHECK_COMMON_TYPE (decltype(-q), mpf_class, mpf_class);
 
-  /* Not currently supported
+  /* These require a common_type specialization */
+  CHECK_COMMON_TYPE (decltype(-z), decltype(z+z), mpz_class);
+  CHECK_COMMON_TYPE (decltype(-q), decltype(q+q), mpq_class);
+  CHECK_COMMON_TYPE (decltype(-f), decltype(f+f), mpf_class);
+
   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);
+  CHECK_COMMON_TYPE (decltype(-z), decltype(-f), mpf_class);
+  CHECK_COMMON_TYPE (decltype(-q), decltype(-f), mpf_class);
+
+  /* These could be broken by a naive common_type specialization */
+  CHECK_COMMON_TYPE (decltype(-z), decltype(-z), decltype(-z));
+  CHECK_COMMON_TYPE (decltype(-q), decltype(-q), decltype(-q));
+  CHECK_COMMON_TYPE (decltype(-f), decltype(-f), decltype(-f));
+
+  /* Not yet supported
+  CHECK_COMMON_TYPE_BUILTIN (decltype(-z), mpz_class);
+  CHECK_COMMON_TYPE_BUILTIN (decltype(-q), mpq_class);
+  CHECK_COMMON_TYPE_BUILTIN (decltype(-f), mpf_class);
   */
 }
 


More information about the gmp-commit mailing list