1

I maintain an open-source library that is supposed to run on multiple platforms and offers (among other) mathematical routines on native data types. We want to offer 64 bit calculations wherever possible.

Our target platforms are Linux and OSX on 32 bit and 64 bit, Windows is not supported yet but most of the code is known to run under Windows and thus we'd keep the possibility to easily port to Windows in the not-so-distant future. Hence, as for http://en.cppreference.com/w/cpp/language/types, we are interested in ILP32, LLP64 and LP64. We also interact with gmp (which only offers constructors for int and long, but not long long.)

We now ran into problems that boiled down to which native integer types we use as a default for our number type:

  • If we use int, we fall back to 32 bits on 64 bit platforms.
  • If we use long, we have inconsistent behavior between Linux/OSX 64 vs. Windows 64: Windows will fail to employ 64 bit calculations.
  • If we use long long, using gmp becomes a mess because creating mpz_class from a long long results in an ambiguous overload. We'd have to cast the numbers beforehand back to long (and thus effectively using only 32 bits on Windows in a number of places.)
  • If we use std::int64_t and alike, the typedefs differ between platforms and thus we get the same problems, just different ones for each platform...

Is there some kind of best practice for that? Is it even possible to avoid these problems or are they inherent to the C++ type system?

Of course, the problems don't end here. Further open questions to be considered:

  • How do each of these solutions interact with for example std::size_t? std::size_t has it's purpose, but sometimes it needs to interact with the numbers we calculate on. Obviously, we don't want to cast back and forth all the time.
  • How do we handle usage with other number types? If we offer a function f(T) and provide overloads for T = int,long,long long but the user uses it with std::int64_t, can we avoid inconsistent behavior between different platforms? (that have differing definitions of std::int64_t) If we also provide overloads for std::int64_t, we'll have duplicate overloads.

PS: I already read c-long-long-int-vs-long-int-vs-int64-t and should-i-use-long-long-or-int64-t-for-portable-code. I got some insight there what exactly happens and why it is like this, but could not derive a solution...

Community
  • 1
  • 1
nafur
  • 181
  • 4
  • Not sure what the question is. `std::int64_t` is a 64-bit integer type in any conforming implementation. `std::size_t` should not have any relationship whatsoever with your numbers, this is a type to express size of the object, nothing more, nothing else. And last, but not the least, never use `long` if there is any attempt at portability whatosoever. It is **the** most fluctuating type. I even know an environment where `long` is checked at checkin type, and having it in your code is a block for checkin. – SergeyA Mar 21 '16 at 17:45
  • @SergeyA The problem with the `intN_t` family of types is they do not have to exist. – NathanOliver Mar 21 '16 at 17:47
  • @NathanOliver, OP mentions OS X, Linux and Windows. They do exist on major C++ implementations used on those platforms. – SergeyA Mar 21 '16 at 17:49

1 Answers1

0

It looks like by definition your gmp on Windows will never support 64 bit values. So I'd suggest just using int64_t in your code, and anytime you need to interact with gmp first static_cast the value to long.

Mark B
  • 95,107
  • 10
  • 109
  • 188