summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Glisse <marc.glisse@inria.fr>2012-02-18 13:22:19 +0100
committerMarc Glisse <marc.glisse@inria.fr>2012-02-18 13:22:19 +0100
commit0a930a699bb4418754338f2eb07bda931f3a42fa (patch)
tree40e8316c9d189aa5d668edb8999d4c420d9cac9d
parent13bdb26019f57b8f16808815a347a57ca4e81299 (diff)
downloadgmp-0a930a699bb4418754338f2eb07bda931f3a42fa.tar.gz
Specialize std::common_type in C++11.
-rw-r--r--ChangeLog5
-rw-r--r--gmpxx.h26
-rw-r--r--tests/cxx/t-cxx11.cc50
3 files changed, 76 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index eaba4c990..5346640f4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2012-02-18 Marc Glisse <marc.glisse@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@inria.fr>
* gmp-h.in (__GMP_WITHIN_GMP): Test with #ifdef instead of #if, for
diff --git a/gmpxx.h b/gmpxx.h
index 31c6f1da9..547960d21 100644
--- a/gmpxx.h
+++ b/gmpxx.h
@@ -42,13 +42,18 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
#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
+#if __GMPXX_USE_CXX11
+#define __GMPXX_NOEXCEPT noexcept
+#include <type_traits> // for common_type
+#else
+#define __GMPXX_NOEXCEPT
+#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 @@ struct __gmp_resolve_expr<mpf_t, mpq_t>
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 --git a/tests/cxx/t-cxx11.cc b/tests/cxx/t-cxx11.cc
index 8c4473c03..578f9b7e5 100644
--- a/tests/cxx/t-cxx11.cc
+++ b/tests/cxx/t-cxx11.cc
@@ -45,10 +45,40 @@ 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")
+#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 @@ void check_common_type ()
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);
*/
}