[Simulator->Hardware]Mbed not compiling functions

Hello,
I hate to keep asking these beginner questions :confused: but i have been programming on the simulator for quite a while and wanted to try compile my game in Mbed but i kept getting errors even though building in the simulator works.
Does anyone know why compiling this does not work?

These are the contents of my_settings.h

/**************************************************************************/
/*!
@file My_settings.h
@author XX

@section HOW TO USE My_settings

My_settings can be used to set project settings inside the mbed online IDE
*/
/**************************************************************************/

#define PROJ_HIRES 0
#define PROJ_ENABLE_SOUND 0

thanks for your help :slight_smile:

1 Like

Thatā€™s Ok. Itā€™s my fault for not providing more documentation.

Try pok.buttons.pollButtons

(explanation: in the Sim version, it seems I have forgotten to remove pollButtons from the upper layer, and it does not exist in the hardware version of the library)

1 Like

Thanks that worked. I am still wondering why though since everything worked in the simulator and there is more stuff that doesent behave the same way.

Mbed doesent seem to like me using the atan2() and abs() functions they both give me pretty much the same error: ā€œError: More than one instance of overloaded function ā€œabsā€ matches the argument list in ā€œmain.cppā€, Line: 930, Col: 41ā€

If i remove the lines with these functions the game compiles (but i kinda need the functions :stuck_out_tongue: )

Thanks!

EDIT:

Copy-paste the problematic code here and Iā€™ll also check it out.

This is the functtion that uses abs()

void spawnEnemy() {
    if (pok.getTime() - spawnCounter > max(abs(SPAWN_TIMER - score * 10), 500)) {
        spawnCounter = pok.getTime();
        //sapwn fat
        if (random(0, 5) == 0 && !fatState) {
            fatState = true;
            fatX = random(0, 100);
            fatHealth = FAT_HEALTH;
        }
        //spawn normal
        for (int i = 0; i < 10; i++) {
            if (!enemyState[i]) {
                enemyState[i] = true;
                enemyX[i] = random(0, 102);
                enemyY[i] = 89;
                return;
            }
        }
    }
    //If code is here no more enemies could spawn
    return;
}

and this is the functin that uses atan2()

int getAngle(int x1, int y1, int x2, int y2) {
    float pi = 3.14159265359;
    int angle = (atan2(y1 - y2, x1 - x2))*180 / pi;
    angle = (((-angle) % 360)+ 360)% 360;
    return angle;
}

Yep. I found the reason for it:

The problem (probably) is you have a mix of ints and floats inside the abs().

You need to int(x) or (int)x to change x into an int if its a float

Iā€™m not 100% sure but it looks to be the cause. Lets continue looking into this.

1 Like

@Xhaku :

This compiles OK, so Iā€™m looking at max next

#include "Pokitto.h"

Pokitto::Core game;

int main () {
    game.begin();
    
    while (game.isRunning()) {
        if (game.update()) {
            game.display.print(abs(-4.0f-(int)2));
            } 
    
    }
}

Solution:

SPAWN_TIMER and score should be both floats or explicitly type converted into floats inside the abs() (see similar example on atan2 below)

You can see the syntax of the commands by stopping the cursor on top of the function/symbol. A window pops up on the right hand corner:

You can see there is no atan2(int,int). So you need to do a bit of typecasting first.

This does not work:

int x,y;
game.display.print(atan(x,y));

Results in:

Error: More than one instance of overloaded function ā€œatan2ā€ matches the argument list in ā€œmain.cppā€, Line: 10, Col: 33

Solution:

But this (with explicit type conversion from int to double) works:

int x,y;
game.display.print(atan2((double)x,(double)y));

As for the reason why the behaviour is different in the simulator (C++11) vs. online mbed IDE (C++03):

jamcro01James Crosbymbed staff
Oct '15
Hi David,
We will be targeting C++11, but not all of our supported compilers have a C++11 standard library yet.
In practice that means we are currently targeting C++98 (functionally equivalent to C++03), and intend to turn on some useful C++11 features over time.

From:

2 Likes

Thanks i got everything to work!

2 Likes

If you want to know exactly why this was an error, here I am to explain.
(And if you didnā€™t want to know, here I am to spoil your day. :P)

@jonneā€™s right that itā€™s related to C++11 vs C++98, but hereā€™s the exact reason.

In C++98 there were only three versions of atan2 in the cmath library:

float atan2(float, float);
double atan2(double, double);
long double atan2(long double, long double);

Youā€™ve been calling it like this:

atan2(y1 - y2, x1 - x2)

y1, y2, x1 and x2 are all ints,
therefore y1 - y2 is also an int, and x1 - x2 is also an int.

So youā€™re effectively trying to call atan(int, int), but no such function exists,
so the compiler has to decide with of the three previous functions to callā€¦

The compiler has the choice of changing your ints to floats, to doubles or to long doubles.
Sadly thereā€™s no rule saying which of those three is a better choice, so the compiler canā€™t decide.
When the compiler canā€™t decide which function to use it throws an error - essentially asking you to help it pick one.

Fast forward 13 years to C++11, and now thereā€™s a more versions of atan2 available.
Importantly, there is now a:

double atan2(int, int);

So the compiler is no longer stuck about which function to chose,
it just selects double atan2(int, int) and you donā€™t have to worry about anything.

And the moral of this story is: C++98 sucks, C++11 is awesome. :P


Footnote

Iā€™m actually slightly lying about there being a double atan2(int, int), itā€™s more complicated than that, but the truth involves templates and I donā€™t want to scare anyone.

Read on if you're not afraid of templates

The truth is, atan2 is probably defined a bit like this:

template<typename Left, typename Right>
double atan2(Left left, Right right)
{
	static_assert(std::is_integral<Left>::value, "Error: left argument of atan2 is not an integral type");
	static_assert(std::is_integral<Right>::value, "Error: right argument of atan2 is not an integral type");
	return atan2(static_cast<double>(left), static_cast<double>(right));
}

template<typename Left>
long double atan2(Left left, long double right)
{
	static_assert(std::is_integral<Left>::value, "Error: left argument of atan2 is not an integral type");
	return atan2(static_cast<long double>(left), right);
}

template<typename Right>
long double atan2(long double left, Right right)
{
	static_assert(std::is_integral<Right>::value, "Error: right argument of atan2 is not an integral type");
	return atan2(left, static_cast<long double>(right));
}
1 Like