What's the difference in GCC between -std=gnu++0x and -std=c++0x and which one should be used?

Meh picture Meh · Feb 27, 2011 · Viewed 10.6k times · Source

I'm having troubles with <stdint.h> when using -std=c++0x in GCC 4.4.3 (for Android):

// using -std=c++0x
#include <stdint.h>
uint64_t value;  // error: 'uint64_t' does not name a type

But using -std=gnu++0x works:

// using -std=gnu++0x
#include <stdint.h>
uint64_t value;  // OK

Is <stdint.h> incompatible with C++0x?

Answer

Steve Jessop picture Steve Jessop · Feb 27, 2011

So far as I can tell, I think this could be argued an implementation bug (or actually, since C++0x isn't published, not a bug per se but an incomplete implementation of the current state of the upcoming standard).

Here's why, referring to n3225 for the expected behavior of -std=c++0x:

D.7 says

Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope

OK, so far so easy. What does <cstdint> place in the standard library namespace?

18.4.1:

typedef unsigned integer type uint64_t; // optional

How optional? 18.4.1/2:

The header defines all functions, types, and macros the same as 7.18 in the C standard

Drat. What does the C standard say? Taking out n1256, 7.18.1.1/3:

These types are optional. However, if an implementation provides integer types with widths of 8, 16, 32, or 64 bits, no padding bits, and (for the signed types) that have a two's complement representation, it shall define the corresponding typedef names

But hang on, surely on Android with -std=c++0x GCC does provide a 64 bit unsigned type with no padding bits: unsigned long long. So <cstdint> is required to provide std::uint64_t and hence stdint.h is required to provide uint64_t in the global namespace.

Go on, someone tell me why I'm wrong :-) One possibility is that C++0x refers to "ISO/IEC 9899:1999 Programming languages — C" without specifying a version. Can it really be that (a) 7.18.1.1/3 was added in one of the TCs, and also (b) C++0x intends to reference the original standard as of 1999, not the amendments since then? I doubt either of these is the case, but I don't have the original C99 on hand to check (a) and I'm not even sure how to check (b).

Edit: oh, as for which one should be used -std=c++0x isn't really a strict standards-compliant mode yet, since there isn't a strict standard yet. And even if there was a standard, gcc 4.4.3 certainly isn't a finished implementation of it. So I see no great need to use it if -std=gnu++0x is actually more complete, at least in this respect for your combination of gcc version and platform.

However, gnu++0x will enable other GNU extensions, that you might not want your code to use. If you're aiming to write portable C++0x, then eventually you'd want to switch to -std=c++0x. But I don't think GCC 4.4 or any other C++0x implementation-in-progress is complete enough yet for it to be practical to write code from the (draft) standard, such that you could say with a straight face "I'm programming C++0x, and it's only 2011!". So I'd say, use whichever one works, and understand that whichever one you use now, you'll probably be switching to -std=c++11 eventually anyway.