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 int
s,
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 int
s to float
s, to double
s or to long double
s.
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));
}