How do you construct a long long in gcc, similar to constructing an int via int()
The following fails in gcc (4.6.3 20120306) (but passes on MSVC for example).
myFunctionCall(someValue, long long());
with error expected primary-expression before 'long' (the column position indicates the first long is the location).
A simple change
myFunctionCall(someValue, (long long)int());
works fine – that is construct an int and cast to long long – indicating that gcc doesn’t like the long long ctor.
Summary Solution
To summarize the brilliant explanation below from @birryree:
- many compilers don’t support
long long()and it may not be standards compliant - constructing
long longis equivalent to the literal0LL, so usemyFunctionCall(someValue, 0LL) - alternatively use a
typedef long_long_t long longthenlong_long_t() - lastly, consider using
uint64_tif you are after a type that is exactly 64 bits on any platform, rather than a type that is at least 64 bits, but may vary on different platforms.
I wanted a definitive answer on what the expected behavior was, so I posted a question on
comp.lang.c++.moderatedand got some great answers in return. So a thank you goes out to Johannes Schaub, Alf P. Steinbach (both from SO), and Francis Glassborrow for some informationThis is not a bug in GCC – in fact it will break across multiple compilers – GCC 4.6, GCC 4.7, and Clang complain about similar errors like
primary expression expected before '('if you try this syntax:Some primitives have spaces, and that is not allowed if you want to use the constructor-style initialization because of binding (
long()is bound, butlong long()has a freelong). Types with spaces in them (likelong long) can not use thetype()-construction form.MSVC is more permissive here, though technically non-standard compliant (and it’s not a language extension that you can disable).
Solutions/Workarounds
There are alternatives for what you want to do:
Use
0LLas your value in place of attemptinglong long()– they would produce the same value.This is how most code will be written too, so it will be most understandable to anyone else reading your code.
From your comments it seems like you really want
long long, so you cantypedefyourself to always guarantee you have along longtype, like this:Use a template to get around needing explicit naming:
As I mentioned in my comments, you can use an aliased type, like
int64_t(from<cstdint>), which across common platforms is atypedef long long int64_t. This is a more platform dependent than the previous items in this list.int64_tis a fixed-width type that is 64-bits, which is typically how widelong longis on platforms like linux-x86 and windows-x86.long longis at least 64-bit wide, but can be longer. If your code will only run on certain platforms, or if you really need a fixed-width type, this might be a viable choice.C++11 Solutions
Thanks to the C++ newsgroup, I learned some additional ways of doing what you want to do, but unfortunately they’re only in the realm of C++11 (and MSVC10 doesn’t support either, and only very new compilers either way would):
The
{}way:Using what Johannes refers to as the ‘bord tools’ in C++11 with
std::common_type<T>So is there a real difference between
()and initializing with0for POD types?You say this in a comment:
Well, for primitive types, that is not true at all.
From Section 8.5 of the ISO C++ Standard/2003 (don’t have 2011, sorry, but this information didn’t change too much):
The last clause is most important here because
long long,unsigned long,int,float, etc. are all scalar/POD types, and so calling things like this:Is exactly the same as doing this:
Generated code example
Here is a more concrete example of what actually happens in code:
Compile this with:
And I get this in the generated tree dump:
Generated Code Implications
So from the code tree generated above, notice that all my variables are just being initialized with
0, even if I use constructor-style default initialization, like withint mi = int(). GCC will generate code that just doesint mi = 0.My template function that just attempts to do default construction of some passed in
typename T, whereT = unsigned long long, also produced just a0-initialization code.Conclusion
So in conclusion, if you want to default construct primitive types/PODs, it’s like using
0.