Problem (with fix) concerning GMP's C++ random number class
If you take the following code, that comes straight from the manual of GMP 4.1, and try to compile it with a strictly conforming C++ compiler, you will see that it does not compile. --------------------------------------------- #include <gmpxx.h> void foo() { gmp_randclass rg(gmp_randinit_default); } --------------------------------------------- The reason is that, while the constructors for `gmp_randclass' have all been declared to take a C++ function pointer, the invocation above passes a C function pointer. This is not allowed by the C++ standard. One possibility to rectify things is the patch below, which changes the declarations of the constructors. Of course, the dual change is also possible, the point being that C linkage and C++ linkage are incompatible. All the best Roberto -- Prof. Roberto Bagnara Computer Science Group Department of Mathematics, University of Parma, Italy http://www.cs.unipr.it/~bagnara/ mailto:bagnara@cs.unipr.it *** /usr/local/distrib/gmp-4.1/gmpxx.h 2002-05-08 01:09:50.000000000 +0200 --- gmpxx.h 2002-11-05 15:03:05.000000000 +0100 *************** *** 4968,4973 **** --- 4968,4981 ---- } }; + extern "C" typedef void GMP_RANDINIT_DEFAULT(gmp_randstate_t); + extern "C" typedef void GMP_RANDINIT_LC_2EXP(gmp_randstate_t, + mpz_srcptr, + unsigned long int, + unsigned long int); + extern "C" typedef void GMP_RANDINIT_LC_2EXP_SIZE(gmp_randstate_t, + unsigned long int); + class gmp_randclass { private: *************** *** 4988,5004 **** } // gmp_randinit_default ! gmp_randclass(void (*f)(gmp_randstate_t)) { f(state); } // gmp_randinit_lc_2exp ! gmp_randclass(void (*f)(gmp_randstate_t, mpz_srcptr, ! unsigned long int, unsigned long int), mpz_class z, unsigned long int l1, unsigned long int l2) { f(state, z.get_mpz_t(), l1, l2); } // gmp_randinit_lc_2exp_size ! gmp_randclass(int (*f)(gmp_randstate_t, unsigned long int), unsigned long int size) { f(state, size); } --- 4996,5011 ---- } // gmp_randinit_default ! gmp_randclass(GMP_RANDINIT_DEFAULT* f) { f(state); } // gmp_randinit_lc_2exp ! gmp_randclass(GMP_RANDINIT_LC_2EXP* f, mpz_class z, unsigned long int l1, unsigned long int l2) { f(state, z.get_mpz_t(), l1, l2); } // gmp_randinit_lc_2exp_size ! gmp_randclass(GMP_RANDINIT_LC_2EXP_SIZE* f, unsigned long int size) { f(state, size); }
Roberto Bagnara <bagnara@cs.unipr.it> writes:
a strictly conforming C++ compiler,
For instance? g++ 3.2 -pedantic has no objections to the current code.
+ extern "C" typedef void GMP_RANDINIT_DEFAULT(gmp_randstate_t);
Can this be private to gmp_randclass, or given within the definitions of the constructors? If not then they'll want to be prefixed like __gmp_randinit_default_t, or some such.
Kevin Ryde wrote:
Roberto Bagnara <bagnara@cs.unipr.it> writes:
a strictly conforming C++ compiler,
For instance? g++ 3.2 -pedantic has no objections to the current code.
For instance Comeau C++ compiler with option --strict and (IIRC, but I don't have it handy at the moment) Intel's icc compiler with the -Xc option (select strict ANSI C/C++ conformance dialect). However, the point is that the code I have indicated violates the standard; as C++ compiler are moving more and more towards standard conformance the problem may show up at any time with any compiler.
+ extern "C" typedef void GMP_RANDINIT_DEFAULT(gmp_randstate_t);
Can this be private to gmp_randclass, or given within the definitions of the constructors? If not then they'll want to be prefixed like __gmp_randinit_default_t, or some such.
You are right of course (indeed I was expecting Gerardo, as the father, of the C++ interface, would elaborate on the idea so as to suit his taste). I will provide a better patch at the soonest (since I really hope it could be incorporated in the next GMP's release). All the best Roberto -- Prof. Roberto Bagnara Computer Science Group Department of Mathematics, University of Parma, Italy http://www.cs.unipr.it/~bagnara/ mailto:bagnara@cs.unipr.it
Kevin Ryde wrote:
+ extern "C" typedef void GMP_RANDINIT_DEFAULT(gmp_randstate_t);
Can this be private to gmp_randclass, or given within the definitions of the constructors?
No, unfortunately it cannot.
If not then they'll want to be prefixed like __gmp_randinit_default_t, or some such.
The patch below implements this idea. Tested with G++ 3.2, Comeau C/C++ 4.3.0.1 (both with and without --strict) and Intel(R) C++ Compiler for 32-bit applications, Version 6.0.1, Build 20020822Z (the latest version, both with and without -Xc). All the best Roberto -- Prof. Roberto Bagnara Computer Science Group Department of Mathematics, University of Parma, Italy http://www.cs.unipr.it/~bagnara/ mailto:bagnara@cs.unipr.it *** gmpxx.h.orig Mon Nov 4 10:00:43 2002 --- gmpxx.h Fri Nov 8 16:08:23 2002 *************** *** 4968,4973 **** --- 4968,4981 ---- } }; + extern "C" typedef void __gmp_randinit_default_t(gmp_randstate_t); + extern "C" typedef void __gmp_randinit_lc_2exp_t(gmp_randstate_t, + mpz_srcptr, + unsigned long int, + unsigned long int); + extern "C" typedef void __gmp_randinit_lc_2exp_size_t(gmp_randstate_t, + unsigned long int); + class gmp_randclass { private: *************** *** 4988,5004 **** } // gmp_randinit_default ! gmp_randclass(void (*f)(gmp_randstate_t)) { f(state); } // gmp_randinit_lc_2exp ! gmp_randclass(void (*f)(gmp_randstate_t, mpz_srcptr, ! unsigned long int, unsigned long int), mpz_class z, unsigned long int l1, unsigned long int l2) { f(state, z.get_mpz_t(), l1, l2); } // gmp_randinit_lc_2exp_size ! gmp_randclass(int (*f)(gmp_randstate_t, unsigned long int), unsigned long int size) { f(state, size); } --- 4996,5011 ---- } // gmp_randinit_default ! gmp_randclass(__gmp_randinit_default_t* f) { f(state); } // gmp_randinit_lc_2exp ! gmp_randclass(__gmp_randinit_lc_2exp_t* f, mpz_class z, unsigned long int l1, unsigned long int l2) { f(state, z.get_mpz_t(), l1, l2); } // gmp_randinit_lc_2exp_size ! gmp_randclass(__gmp_randinit_lc_2exp_size_t* f, unsigned long int size) { f(state, size); }
participants (2)
-
Kevin Ryde -
Roberto Bagnara