views:

172

answers:

7

I occasionally use 64 bit arithmetic in an open source C++ library of mine. I discovered that long long serves my purpose quite nicely. Even some 10 year old solaris box could compile it. And it works without messing around with #defines on Windows too.

Now the issue is I get complaints from my users because they compile with GCC -pedantic settings, and GCC insists on issuing warnings that long long is not part of the C++ standard. This is probably right, but I am not too interested in the C++ standard per se, I just want my code to work on as many compilers as reasonably possible.

So my question is twofold:

  • can anyone name actual C++ compilers that don't support 64 bit long long's?
  • is there a way to make GCC compile 64 bit arithmetic (on 32 bit platform) without compiler warnings? (stdint.h does not help, as it also depends on long long)

P.S.

If there are platforms where long longs become 128 bit or bigger, that is interesting, but not a problem for me.

+5  A: 

In GCC use the -Wno-long-long compiler option to suppress that particular warning.

You could also use -std=C++0x, but will probably reduce portability further.

Clifford
I am really hoping it can be fixed without a command line switch, but thanks, anyway.
jdv
+3  A: 

You can silence the warning with -Wno-long-long (make sure it comes after -pedantic). 64-bit integers are required by C99 and I think also C++0x so compilers that don't have them are getting rare nowadays.

Zack
I don't think `long long` support is required by C99, but I think it is required by C++0x.
Brian
I'm 100% certain it's in C99, but I'm pretty sure it's not in C++98. (It was a huge deal at the time, because Microsoft forced the committee to accept "`sizeof(size_t) > sizeof(long)`" as a legitimate ABI option, which C89 promised would never happen.)
Zack
@Zack: I will keep the argument about C99 in mind.
jdv
A: 

You could replace your use of long long with one of the many C++ bigint libraries. I'm sure some of them avoid this compiler error. Personally, I'd rather stick with the error.

Brian
+3  A: 

If you're unable to control the switches passed to gcc, you might be able to turn off the warning with a #pragma.

http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html

Mark Ransom
+7  A: 

When your library is provided as source, one option is to provide a "porting" header, in which it is your users' responsibility to provide a 64 bit type (you'd specify the name). It's then also naturally their responsibility to deal with any compiler warnings that their choice of type provokes, either avoid them, suppress them, or ignore them.

I guess this is what you call "messing around with #defines", but I don't think there's too much wrong with it. You can provide a default version which just uses long long directly and will work on your 10-year-old Solaris box and also on Windows, so most users would never need to go near the user-configurable part of your library.

Then for the pedantic users, you can provide a version for GCC which includes <sys/types.h> and uses int64_t instead of long long. This doesn't provoke any warning for me with g++ -pedantic. You could even do this in the default version by recognising GCC, which certainly is messing around with #defines, but again not in a way that's at all unusual for a multi-platform product.

If your library is also provided as binaries for certain platforms, then of course you have to decide what the 64 bit type is going to be. If it also appears in the library interface (and hence the header file), then you'll just have to choose one which will not provoke any warnings with reasonable compiler options. I think -pedantic is a reasonable compiler option, and apparently so do your users, so again that's int64_t on GCC.

Steve Jessop
+1, I think int64_t is the best solution here.
rmeador
I do have a config.h. At some point in time I already was using `int64_t` (from stdint.h), but ditched it in favour of long long because the latter was so much wider supported. The interesting thing is that `int64_t` (from stdint.h) does work, even though it is typedef for `long long` (on my system). Beats me, but thanks for setting me on the right track.
jdv
@jdv: That's because of the thing that Void mentions: GCC's header uses `__extension__`, in `/usr/include/sys/_types.h` on my machine.
Steve Jessop
So far I tested with mingw, and there `sys/types.h` does not define `int64_t`. It gets it from `<stdint.h>`, and __extension__ is not used. Well, it works, that counts for me....
jdv
@jdv: oh well, I'm slightly puzzled then. I didn't actually check whether `/usr/include/sys/_types.h` is where `int64_t` is defined for my usual compile: I have at least three versions of `gcc` installed under `cygwin`, so that file could be from one of the others or could be unused. Could just be that GCC hides all deprecation/extension warnings generated by certain headers.
Steve Jessop
+3  A: 

You can also suppress the warning using gcc's "__extension__" feature, e.g.:

// No '-pedantic' warning/error.
__extension__ long long foo = 2;

// Exhibits '-pedantic' warning/error.
long long bar = 3

and the compile:

$ g++ -pedantic -fsyntax-only foo.cpp
foo.cpp:5: error: ISO C++ 1998 does not support 'long long'

Notice that only the last use of long long triggered the -pedantic error since no __extension__ was prepended. Regardless, I'd go with @Steve Jessop's suggestion of using int64_t instead.

Void
+1  A: 

If you have Boost in a system include directory, you can say

#include "boost/cstdint.hpp"
boost::int64_t my_64_bit_number;

If it is in a system include directory, warnings are automatically suppressed.

Philipp
I wont be using this suggestion, as I'm not using boost yet. But thanks.
jdv