C++ Interface Limitations
=========================
`mpq_class' and Templated Reading
A generic piece of template code probably won't know that
`mpq_class' requires a `canonicalize' call if inputs read with
`operator>>' might be non-canonical. This can lead to incorrect
results.
`operator>>' behaves as it does for reasons of efficiency. A
canonicalize can be quite time consuming on large operands, and is
best avoided if it's not necessary.
But this potential difficulty reduces the usefulness of
`mpq_class'. Perhaps a mechanism to tell `operator>>' what to do
will be adopted in the future, maybe a preprocessor define, a
global flag, or an `ios' flag pressed into service. Or maybe, at
the risk of inconsistency, the `mpq_class' `operator>>' could
canonicalize and leave `mpq_t' `operator>>' not doing so, for use
on those occasions when that's acceptable. Send feedback or
alternate ideas to <bug-gmp@gnu.org>.
Subclassing
Subclassing the GMP C++ classes works, but is not currently
recommended.
Expressions involving subclasses resolve correctly (or seem to),
but in normal C++ fashion the subclass doesn't inherit
constructors and assignments. There's many of those in the GMP
classes, and a good way to reestablish them in a subclass is not
yet provided.
Templated Expressions
A subtle difficulty exists when using expressions together with
application-defined template functions. Consider the following,
with `T' intended to be some numeric type,
template <class T>
T fun (const T &, const T &);
When used with, say, plain `mpz_class' variables, it works fine:
`T' is resolved as `mpz_class'.
mpz_class f(1), g(2);
fun (f, g); // Good
But when one of the arguments is an expression, it doesn't work.
mpz_class f(1), g(2), h(3);
fun (f, g+h); // Bad
This is because `g+h' ends up being a certain expression template
type internal to `gmpxx.h', which the C++ template resolution
rules are unable to automatically convert to `mpz_class'. The
workaround is simply to add an explicit cast.
mpz_class f(1), g(2), h(3);
fun (f, mpz_class(g+h)); // Good
Similarly, within `fun' it may be necessary to cast an expression
to type `T' when calling a templated `fun2'.
template <class T>
void fun (T f, T g)
{
fun2 (f, f+g); // Bad
}
template <class T>
void fun (T f, T g)
{
fun2 (f, T(f+g)); // Good
}