12.6 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 .

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
}
C++11

C++11 provides several new ways in which types can be inferred: auto, decltype, etc. While they can be very convenient, they don’t mix well with expression templates. In this example, the addition is performed twice, as if we had defined sum as a macro.

mpz_class z = 33;
auto sum = z + z;
mpz_class prod = sum * sum;

This other example may crash, though some compilers might make it look like it is working, because the expression z+z goes out of scope before it is evaluated.

mpz_class z = 33;
auto sum = z + z + z;
mpz_class prod = sum * 2;

It is thus strongly recommended to avoid auto anywhere a GMP C++ expression may appear.