diff options
author | Marc Glisse <marc.glisse@inria.fr> | 2012-02-18 13:22:19 +0100 |
---|---|---|
committer | Marc Glisse <marc.glisse@inria.fr> | 2012-02-18 13:22:19 +0100 |
commit | 0a930a699bb4418754338f2eb07bda931f3a42fa (patch) | |
tree | 40e8316c9d189aa5d668edb8999d4c420d9cac9d | |
parent | 13bdb26019f57b8f16808815a347a57ca4e81299 (diff) | |
download | gmp-0a930a699bb4418754338f2eb07bda931f3a42fa.tar.gz |
Specialize std::common_type in C++11.
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | gmpxx.h | 26 | ||||
-rw-r--r-- | tests/cxx/t-cxx11.cc | 50 |
3 files changed, 76 insertions, 5 deletions
@@ -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 @@ -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); */ } |