Hi,

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.

Luke, do you mean this (boost/polygon/polygon_traits.hpp):

    typedef typename coordinate_traits<T>::coordinate_distance area_type;

where compilation fails?

Or this (same file):

    area_type x1 = (area_type)x(previous);
    area_type x2 = (area_type)x(*begin_range);

I didn't reach this point but I'm quite sure that Boost.Units will not accept this C cast, if area_type is square_meters and coordinates are in meters.

Maybe you can try it with Boost.Polygon, and deliver a working example for it, because I got immediately stuck.



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.


I doubt if Boost.Units quantity is really an UDT in the sense UDT is normally used. Boost.Geometry fully supports ttmath (great lib!), and two other high precision arithmetic numbers (GMP/CLN). It is highly probable that other UDT's defining all mathematic operations (operators, functions) are supported as well.

Boost.Units adds something more: physics. Therefore, it forbids mathematical operations as a*b because the result are not meters, but square meters. To support that, more is necessary indeed. Let's call this type an UDT+.

It is (probably) therefore that the review report stated: "The library does not need to be completetly integrated with Boost.Units, although it appears to be reasonable to deal with types as exposed by Boost.Units especially for distance and area calculations.". I think that is handled.


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.

Maybe not in the physical meaning that Boost.Units is using; this is not required and not planned.

I cannot speak of the other libraries, but I think the proposal I wrote yesterday is sufficient: the input is a Boost.Units quantity, the output is a Boost.Units quantity, all in their correct physical meanings. What is happening internally, and we do many many calculations there, all that is detail, black box for this UDT+.

Regards, Barend