On May 26, 2014, at 1:34 PM, "Hartmut Kaiser"
Thank you for your input. It's much appreciated. From the critical tone of your post I'll take it you are voting "no". If you did not state it by accident, then I am happy to do that for you. If you did not state it intentionally, then I think you should as you should not be shying away from your community responsibilities. :-) Please find my replies below. I intentionally have not cast a vote as I don't have put enough effort into a proper review. My main goal was to support Jeroen in his review.
In any case, I wanted to mention a possible alternative to the design using optional<>. Boost.Filesystem and Boost.Asio give a nice precedent on how to construct a library interface supporting both, throwing and non-throwing functions without introducing penalties for either case (based on Boost.System). Using something similar for Convert seems to be a good idea.
I seem to be managing slowly pulling Jeroen onto my "dark" side :-) but his "conditional yes" vote so far is on the condition of "the interface being simplified for the seemingly simple cases"... which echoes very much with your reservations/revulsions ;-) regarding "optional" deployment. So, so far, IMO his vote can only responsibly be counted as "no"... given that everything else revolves around the proposed interface... that you and Jeroen... and quiet a few others are not exactly happy with... And that's perfectly fine by me. No drama.
Thank you for the Boost.Filesystem and Boost.Asio pointers. Unfortunately, I am not familiar with the libs. If they indeed handle deployment cases similar to those I've been moaning about, then it might be wise to postpone going any further with "convert" and study those libs for already-existing/established solutions... without "optional"-generated controversy... Maybe someone else could shed more light on that?...
You usually add a parameter to your function like this:
// global special error_code object (lives in Boost.System) error_code throws;
void foo(error_code& ec = throws);
then, inside foo() on error you do:
if (error_happened) { if (&ec == &throws) // throw exception else { ec = make_my_error_code(); return; } }
Which means, that if you use it as:
foo();
it will throw on error. However, it will not throw if you write:
error_code ec; foo(ec); if (ec) { // handle error }
Boost.Math uses this in eg the distribution. Also: http://www.boost.org/community/generic_programming.html#policy