
With the exception of (a), these are safe(ish) operations. For (c), the operation is very dimensionally safe. (I'd argue it should be implicit, but I'm fine with being more strict for now.)
The rationale for preventing implicit conversions is that much of the point of this library is to provide dimensional analysis with zero runtime overhead - as soon as you allow implicit unit conversions, that's out the window. In addition, you run the risk of losing precision if implicit conversion is allowed between unit systems having significantly different scales (say astronomical and high energy physics units). Even implicit value_type conversion poses a similar problem, but at least there the precedent is already established with built-in value_types... The performance issue is a big one because one of the major anticipated use areas for this sort of library is numerical computing where performance is critical and no overhead is acceptable at runtime...
For (b) the semantics really are the same as a static_cast since the only thing changing is the type, so it's dimensionally safe even if it's type-dangerous. But (a) I worry about. For something like that I'd rather see another name for the cast since it is a potential hole in the unit system – something like reinterpret_quantity_cast. (There's always reinterpret_cast for doing things that are really unsafe.)
Is it possible to overload the system reinterpret_cast, or is it not really a library function? If it was, that might be an option, too...
I picture a few reasonable casts: (0) Casting equivalent units (meters -> feet). This is very very safe and so should have its own cast (if it has a cast at all). (Perhaps quantity could just have an explicit constructor so that static_cast works? Then a precompiler definition could toggle that "explicit" for those who want this to be implicit.)
Actually this is how it is currently implemented. You can do explicit unit system conversions via constructor, and there is a precompiler option: #define MCS_UNITS_ENABLE_IMPLICIT_CONVERSIONS for enabling implicit conversions. So maybe the value_type quantity_cast is redundant... Let's see what others have to say on the topic...
(2) Adding explicit dimensions to something that's got only general units. That is, quantity<length> -> quantity<meters> but not quantity<length> -> quantity<time>. This seems reasonably safe. (Perhaps that would get quantity_cast?)
As now implemented, if you want to have generic code that works for units of any system, you need to template it on unit system like this (from unit_example_4.cpp): /// the physical definition of work - computed for an arbitrary unit system template<class System,class Y> quantity<unit<System,energy_type>,Y> work(quantity<unit<System,force_type>,Y> F, quantity<unit<System,length_type>,Y> dx) { return F*dx; }
b. Casting back to the enclosed type for use in other libraries. These are both potentially dangerous, but not too bad as long as it allows only conversions to and from enclosed types (e.g., quantity<length> -> double and double -> quantity<time>) but disallows quantity-to- quantity conversion (e.g., quantity<length> -> quantity<time>). (Perhaps reinterpret_quantity_cast?)
This is supported through the value() member function in quantity, too...
So what I'm proposing is three new casts: (1) quantity_static_cast to static_cast the enclosed type. (This would show up in searches for static_cast.) (2) quantity_cast to add or remove quantity information (length <-> meters). (3) reinterpret_quantity_cast to go to and from, e.g., doubles. (This would also show up in searches for quantity_cast and for reinterpret_.) This wouldn't be necessary for scalars since division and multiplication would work, but would be useful for arrays.
I think we basically agree on the desirable functionality; I'm not particularly wedded to the specific syntax I've chosen now, but would like to get more input from others before making changes... Thanks for the comments, Matthias