Construction works here for me, but calculating distance does not.
Because distance behind the screens takes the square root, after
squaring. This requires thorough integration with Boost.Units at
those places, which is not planned.
I understand that integrations with Boost.Units is not planned and
even not desirable.
But making the implicit assumption that
typeof(sqrt(s)) == typeof(s) or that typeof(s*s)==type(s)
makes it incompatible with Boost.units. Those assumptions are good as
defaults but there should be a way to tell Boost.Geometry that
sometimes it is not the case.
I took a stab at a generic solution to this problem of units and data types in a geometry library with Polygon. My coordinate_traits defines a distance time, area type etc. I then look up what data type to use for the return value of a distance or area calculation. Because it is a point of customization the user can specify data types with assoicated Boost.Units. My main concern was overflow at the time, but I think having a point of customization (meta function that can be specialized) and using it consistently would allow a generic geometry library to interoperate with Boost.Units without needing to be integrated with Boost.Units. Generic programing should allow exactly these types of compatibility between libraries without directly coupling them. Is there any reason why this approach wouldn't work?
I agree - the general sloppiness in treating mathematical operators in libraries that are intended to generically support them for UDTs seems to be a widespread problem, even within Boost. For example, std::complex (which "circumvents" the problem by disallowing UDT value types) defines
template<class T> complex<T> operator/(const complex<T>& lhs, const complex<T>& rhs);
However, even for a simple value type (e.g. integers - N.B. not int) this is not correct since integer/integer -> rational so this should really be
template<class T> complex<rational> operator*(const complex<integer>& lhs, const complex<integer>& rhs);
In general, anywhere that
template<class T> something<T> operator blah(const something<T>& lhs, const something<T>& rhs);
appears should look like (pseudocode)
template<class T> something<typeof(T blah T)> operator*(const something<T>& lhs, const something<T>& rhs);
instead. This requires a bit more care, but I think it is demonstrably the right thing to do and should probably be an expectation in Boost libraries. For example, I know that Boost.Quaternions, Boost.Octonions, and Boost.uBlas do not do the right thing in this context. It would also probably make sense to provide a Boost.Complex that allows UDTs and handles them correctly. It sounds like Boost.Geometry also does not correctly handle basic mathematical operators.
Matthias