devkitArm template compilation error w GCC 7.1
category: code [glöplog]
I posted on the devkitPro forum, but that seems pretty dead, so I try again here:
I picked up an old GBA project I would like to finish now. I have a template fixed-point class (IDEOne example) with tests that compiles with GCC 5.4 (my PC) and 6.3 (IDEOne) and even 7.1.0 (wandbox), but not the 7.1 included in the current devkitArm... GCC always tells me that:
Before I go insane: Does anybody have an idea?
I picked up an old GBA project I would like to finish now. I have a template fixed-point class (IDEOne example) with tests that compiles with GCC 5.4 (my PC) and 6.3 (IDEOne) and even 7.1.0 (wandbox), but not the 7.1 included in the current devkitArm... GCC always tells me that:
Code:
/src/test.cpp: In function 'int main()':
/src/test.cpp:7:13: error: call of overloaded 'fp(int)' is ambiguous
fp1616 a0(0);
^
In file included from /src/test.cpp:1:0:
/src/test.h:10:2: note: candidate: fp<F>::fp(const float&) [with int F = 16]
fp(const float & b) : s(b * (1 << F)) { }
^~
/src/test.h:9:2: note: candidate: fp<F>::fp(const int32_t&) [with int F = 16; int32_t = long int]
fp(const int32_t & b) : s(b << F) { }
^~
/src/test.h:4:8: note: candidate: constexpr fp<16>::fp(const fp<16>&)
struct fp
^~
Before I go insane: Does anybody have an idea?
How about this?
0 is of type int, int32_t is long int, which is not the same type, so neither of the two constructors is a match.
Code:
fp1616 a0(int32_t(0));
0 is of type int, int32_t is long int, which is not the same type, so neither of the two constructors is a match.
obviously
fp1616 a0(0.0);
would pose a problem, because of conversion rules (double->float, double->int), but 0 is an int. There should be no confusion about it...
Why is the problem only in the devkitArm 7.1 version?! Because int there is 16bit?
writing
fp1616 a0(int32_t(0));
would work, but seriously, wtf, why would I need to use that everywhere?... :/
fp1616 a0(0.0);
would pose a problem, because of conversion rules (double->float, double->int), but 0 is an int. There should be no confusion about it...
Why is the problem only in the devkitArm 7.1 version?! Because int there is 16bit?
writing
fp1616 a0(int32_t(0));
would work, but seriously, wtf, why would I need to use that everywhere?... :/
Hmm. Ok. Thanks for being the "parrot programmer" ;) This seems to work on both sizeof(int)==2 and 4...
Quote:
would work, but seriously, wtf, why would I need to use that everywhere?... :/
You are taking a reference, hence the type of the provided parameter has to exactly match that of the constructor. If, in this particular environment, int and int32_t are not identical types (which is never guaranteed), then there is no way 0 (which is by definition and "int" literal) can be a const reference to an int32_t. Adding more constructor overloads and/or not making them take references helps here.
wow, that is some hgih-level GBA code :)
If it is a 16/32 bit issue you should be able to force it by using
If it is a 16/32 bit issue you should be able to force it by using
Code:
right? fp1616 a0( 0L );
Quote:
You are taking a reference, hence the type of the provided parameter has to exactly match that of the constructor.
doh. You're right. That is the problem. I've been staring at this stuff for so long now and did not want to change that :/
Quote:
wow, that is some hgih-level GBA code :)
Well, the iostream stuff is only for IDEOne, obviously, but I like the syntactic sugar in comparison to ASM. I hope GCC optimization will take care of most of it. Then do the rest by hand...
Quote:
right?
that will only work as long as an int32_t is indeed a long int, so it would break again on other compilers probably. Hence saying explicitely that it should be an int32_t or not taking references is the safer solution.
not taking references is not enough in all cases for me... :/ but it works now. the template enable_if takes care of other compilers by removing the (int) functions if int == in32_t. works for me (tm) ;)
Why the overload anyway? Years ago I was playing around with a similar class and IIRC gcc was smart enough to compile "* (1 << n)" as a shift for integer types.