I am confused about how implicit type conversion works with regard to C++ argument lists. In particular, I have a bunch of functions called like inRange(x, start, end), which return a bool depending on whether x is between start and end.
[In this description inRange is just syntactic sugar for (x > start && x < end) -- which is still nice when x is a long string or an expensive function -- but in the real code there are extra args for handling the open/closed nature of the boundaries.]
I was vague about the types above. In particular there are different implementations for integer and floating point comparisons, and this meant that templates were not really appropriate since there is no C++ linguistic grouping that differentiates int/long/unsigned/size_t etc. from float/double, etc. So I tried to use the type system by defining two versions of inRange with wide enough int/float types:
inline bool inRange(long x, long start, long end)
inline bool inRange(double x, double start, double end)
This won't catch "long long" or similar, but our code only uses at most doubles and longs. So it looked pretty safe: my hope was that inRange(int, long, long) etc. would implicitly upcast the int to a long and everything would be fine. However, in cases where literal doubles are written sloppily for the floating point comparison (which I want to allow), e.g. inRange(mydouble, 10, 20), I also had to add a bunch of explicit casts to get rid of compiler warnings and ensure that the floating point comparison is used:
inline bool inRange(double value, long low, long high) {
return inRange(value, (double)low, (double)high);
}
inline bool inRange(double value, double low, long high) {
return inRange(value, low, (double)high, lowbound, highbound);
}
...
Not so nice -- I'd hoped that the conversion of long to double would have been automatic/implicit -- but ok. But the next discovery really screwed me: my compiler encountered an inRange with three ints (not longs) as arguments, and said:
call of overloaded ‘inRange(int&, int&, int&)’ is ambiguous
followed by a list of all the inRange functions defined so far! So C++ doesn't have a preference for (int, int, int) arg lists to be resolved by (long, long, long) rather than by (double, double, double)? Really?
Any help to get me out of this hole would be much appreciated... I'd never have thought something so simple with only primitive types involved could turn out to be so hard to resolve. Making the full set of ~1000 three-arg function signatures with all possible numerical type combinations is not the answer I'm hoping for!
std::numeric_limitshas ais_integersee reference.is_trivially_copyable?) cannot be defined in "pure C++". Thus I would argue that the Standard Library is part of the language itself; Boost is an extension ;)