wbhart / mpir

Multiple Precision Integers and Rationals
GNU General Public License v3.0
229 stars 135 forks source link

GCC: call of overloaded ‘__gmp_expr(long long unsigned int)’ is ambiguous #254

Closed BrainStone closed 6 years ago

BrainStone commented 6 years ago

When trying to compile the following snippet:

std::cout << mpz_class( 9681666858668565181LLU ) << std::endl;

with GCC (and Clang, iirc) it results in this compilation error:

/project/code.cpp:1:49: error: call of overloaded ‘__gmp_expr(long long unsigned int)’ is ambiguous
  std::cout << mpz_class( 9681666858668565181LLU ) << std::endl;
                                                 ^
In file included from /root/TruncateablePrimes/src/truncatablePrimes/cpp/main.cpp:8:0:
/project/lib/mpir/include/mpirxx.h:1623:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(double)
   __gmp_expr(double d) { mpz_init_set_d(mp, d); }
   ^~~~~~~~~~
/project/lib/mpir/include/mpirxx.h:1622:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(float)
   __gmp_expr(float f) { mpz_init_set_d(mp, f); }
   ^~~~~~~~~~
/project/lib/mpir/include/mpirxx.h:1607:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(long unsigned int)
   __gmp_expr(unsigned long int l) { mpz_init_set_ui(mp, l); }
   ^~~~~~~~~~
/project/lib/mpir/include/mpirxx.h:1606:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(long int)
   __gmp_expr(signed long int l) { mpz_init_set_si(mp, l); }
   ^~~~~~~~~~
/project/lib/mpir/include/mpirxx.h:1604:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(short unsigned int)
   __gmp_expr(unsigned short int s) { mpz_init_set_ui(mp, s); }
   ^~~~~~~~~~
/project/lib/mpir/include/mpirxx.h:1603:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(short int)
   __gmp_expr(signed short int s) { mpz_init_set_si(mp, s); }
   ^~~~~~~~~~
/project/lib/mpir/include/mpirxx.h:1601:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(unsigned int)
   __gmp_expr(unsigned int i) { mpz_init_set_ui(mp, i); }
   ^~~~~~~~~~
/project/lib/mpir/include/mpirxx.h:1600:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(int)
   __gmp_expr(signed int i) { mpz_init_set_si(mp, i); }
   ^~~~~~~~~~
/project/lib/mpir/include/mpirxx.h:1598:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(unsigned char)
   __gmp_expr(unsigned char c) { mpz_init_set_ui(mp, c); }
   ^~~~~~~~~~
/project/lib/mpir/include/mpirxx.h:1597:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(signed char)
   __gmp_expr(signed char c) { mpz_init_set_si(mp, c); }
   ^~~~~~~~~~
/project/lib/mpir/mpirxx.h:1587:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(__gmp_expr<__mpz_struct [1], __mpz_struct [1]>&&)
   __gmp_expr(__gmp_expr &&z)
   ^~~~~~~~~~
/project/lib/mpir/include/mpirxx.h:1585:3: note: candidate: __gmp_expr<__mpz_struct [1], __mpz_struct [1]>::__gmp_expr(const __gmp_expr<__mpz_struct [1], __mpz_struct [1]>&)
   __gmp_expr(const __gmp_expr &z) { mpz_init_set(mp, z.mp); }
   ^~~~~~~~~~
wbhart commented 6 years ago

My guess is there's no version of mpz_class that takes an LLU.

BrainStone commented 6 years ago

Well my issue is that compiles under VisualStudio and it's being advertised to support 64 bit integers. (Even on 32 bit architecture. But I tried compiling it for both)

Probably should have clarified that in the issue. Will do that tomorrow.

wbhart commented 6 years ago

long is 64 bits on linux. It should work if you use UL instead of LLU.

BrainStone commented 6 years ago

I’ll try it with just the U. As the length should be detected automatically. Though I think I already tried that 🤔
I’ll give it a try later.

wbhart commented 6 years ago

I don't think the same code will work under both compilers. Usually people work around this by defining a macro for constant literals, that expands one way on Windows and another way on Linux.

BrainStone commented 6 years ago

Well one thing is for sure. GCC makes a difference between long int and long long int. Just according to the compiler error itself: __gmp_expr(long long unsigned int)

Anyways why isn’t the lib using unambiguous ints like uint32_t or int64_t. At least for the C++ part? They are standardized for at least C++ and even C if I’m not mistaken.

wbhart commented 6 years ago

This would mean rewriting all code that depends on GMP, which is tens of millions of lines of code.

It's also not as simple as it might seem to get something portable. Not all compilers distinguish long int and long long int (one is an alias for the other), so if you define the functions for both, you end up with a duplicate definition (this is how MPIR used to be, but we had to revert it after this was discovered).

MPIR makes no attempt to turn C/C++ into a portable language. You still have to write portable code when using it.

BrainStone commented 6 years ago

I see. You can't do it right xD

Some people need support for long long int and others don't.

Anyways, I think just using mpz_class( 9681666858668565181U ) should work, as that makes it unsigend (the value is too large for int64_t).

I didn't know that GCC makes a difference between long int and long long int even though they both are 64-bit ints.

I think that concludes this issue. Thank you for your swift support and moreover this wonderful project. Without it I'd still be banging my head against the wall trying to get GMP running on windows ;)