The following code compiles warning-less on a 64-bit Linux system using (native 64-bit) g++-10:
#include <cstdint>
class A {
public:
explicit A(unsigned long long int x) { };
explicit A(uint64_t x) { };
};
int main() {}
However, on a 32-bit system, (same Linux distro, same version, but it is a 32-bit machine), I get this error:
t.cc:6:14: error: ‘A::A(uint64_t)’ cannot be overloaded with ‘A::A(long long unsigned int)’
6 | explicit A(uint64_t x) { };
| ^
t.cc:5:14: note: previous declaration ‘A::A(long long unsigned int)’
5 | explicit A(unsigned long long int x) { };
I tested the bitsizes experimentally (printf-ing sizeof(long long unsigned int)), and yes they are all 8 byte long on both 32 and 64 bit systems.
Why it then does not compile on a 32-bit system?
Extension:
I hunted a little bit for that, and I found in the glibc headers /usr/include/x86_64-linux-gnu/bits/types.h (or /usr/include/i386-linux/bits/types.h) that their defition differs by an __extension__ macro or attribute:
#if __WORDSIZE == 64
typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;
#else
__extension__ typedef signed long long int __int64_t;
__extension__ typedef unsigned long long int __uint64_t;
#endif
I think this __extension__ is the important thing. If __WORDSIZE == 64, thus we are on a 64-bit environment, then these types are compatible. If not, then the type definitions differ by an __extension__. Where is this attribute (macro) from? How to make fair platform-independent code?