
I might have got something wrong, and missed probably something in the manual... So what is a better way of writing this line in the code?
a += (dd*exp(i*k*r)/r).value();
The result of dd*exp(i*k*r)/r is dimensionless, but direct assignment (copy construction) isn't working here. And I would really admire if the code could look in a sane way, like this:
a += dd*exp(i*k*r)/r;
This would look, like I'm not really worrying about using boost::units, just benefit from all the unit checking, and no extra code to type. (and change k to use double, not complex ;) Also I am suspicious that currently my code has a bug here, exactly where the .value() is taken. Because `dd` and `r` are units of different scale.
I don't think you missed anything and I think that your second expression should work as expected. I would consider it a flaw in Boost.Units that this does not currently work and a flaw in C++ that getting a (relatively) simple mathematical concept like dimensional analysis to function in a library is as difficult as it is...
This is an idiosyncrasy of overload resolution. std::complex::operator+= is a template, so an implicit conversion doesn't work. The template argument can't be deduced.
Perhaps we should flesh out the toy complex implementation we wrote and incorporate it in the units library? It is a fairly common thing to use together with units and, as I understand it, the standard only defines complex for a subset of built in types...
that would be great. Because there is no physical reason why wavenumber k would need to be complex. It seems like allowing to perform a conversion from double to complex is reasonable. Only opposite conversion has reasons to fail. Just like converting double to int has reasons to fail. But converting int to double should work flawlessly.
I think we should be able to get such things to behave sensibly.
quantity<length> wavelength ( 632.8 *nano*meters); quantity<length> wavelength = 632.8 *nano*meters; Although, in Janek's defense, this seems overly restrictive. Can we allow copy construction between scaled units and the corresponding unscaled unit without introducing undesirable side effects?
I would really appreciate that :) It would simplify code. Also because I cannot put 632.8*nano*meters directly as arguments to function call.
The currently sanctioned approach to function arguments is to use templates to accept any unit of the appropriate dimension, but it does make more sense to allow implicit conversion in the special case of scaled units. The only issue is the danger of roundoff/truncation problems.
btw, how usually do you define those scaled units to be a little more convenient to use? I mean, just type: 632.8*nm Is there some header to include, to benefit from all standard SI system prefixes? It would be great, it's a standard after all :) And those short names are carefully designed to not have any unit name clashes.
I guess we could have a header corresponding to each SI unit that contains predefined scaled units for each of the SI prefixes.
Of course while writing C++ code we might end up with variables names & units names clashing, like using single letter 'm' for 'meter', but this is why we have an si:: namespace after all. And if my code grows a little bigger I will definitely switch to: 632.8*si::nm
If you will have some changes in library that will need testing I will gladly try it.
If you tell me how to define si::km, si::m, si::kN, si::GJ I can generate for you a header file with all possible units. Though 'micro' is not in latin alphabet. So micro meter is not possible, aww..
I'll try to get you something to start with later today. Matthias