
On 5/9/2011 9:08 AM, Stewart, Robert wrote:
This leaves the fate of the converter function objects unclear. That functionality seems too useful to drop. Two sets are needed now? One set would be for non-streams-based conversions and the other set for streams-based conversions? The latter would support manipulators and the former would not.
To summarize, here's the complete API as I see it now:
1. convert::default_value<T> customization point * Default value, if needed, when not otherwise supplied
2. convert::converter<T,S> customization point * Non-stream-based main logic * Functor interface
3. T convert::convert_cast<T,S>(S) * Throws on failure unless T is convert::result<T'> * Uses convert::converter<T,S> to do conversion
4. T convert::convert_cast<T,S>(S, T _fallback) * Returns _fallback on failure unless T is convert::result<T'> * Uses convert::converter<T,S> to do conversion
5. bool convert::try_converting_to<T,S>(S, T& _value) * Returns false and leaves _value unchanged on failure * Uses convert::converter<T,S> to do conversion
6. convert::stream_converter<T,S> customization point * Stream-based main logic * Functor interface * Supports manipulators
7. T convert::as<T,S>(S, options) * Throws on failure * Uses convert::stream_converter<T,S> to do conversion
8. T convert::as<T,S>(S, T _fallback, options) * Returns _fallback on failure * Uses convert::stream_converter<T,S> to do conversion
9. bool convert::try_as<T,S>(S, T& _value, options) * Returns false and leaves _value unchanged on failure * Uses convert::stream_converter<T,S> to do conversion
Does that cover everything satisfactorily? Did I miss something? Except where I have suggested specific support for convert::result, I don't think it should be allowed. (That is, use SFINAE to ensure that convert::result isn't used with the other parts of the API.)
If that's a decent API, and since it represents the combination of the functionality in both Vicente's and your library, perhaps the two of you could collaborate on it and produce a new Boost.Convert proposal. (I'd prefer Boost.Convert to Boost.Conversion because the namespace name is shorter and more useful when reading names like "convert::as.")
When you say "stream-based main logic" do you mean that it should appear to be using streams, but that it doesn't matter if it really does? It's reasonable to develop optimized string<->numeric converting code that respects locale and manipulators, so I don't think we should exclude the possibility of such implementations. If we're going to create two APIs, I'd rather have one for string<->numeric conversion and one for type<->type conversion. I also don't understand the shift from "convert_cast" to "as". It isn't intuitive why one uses streams and the other doesn't. The specialization for convert::result doesn't bother me, but I suspect it will garner the same criticism as Vladimir's original proposal (i.e. why not optional<T>?). I agree we need to support multiple manipulators, but yuck! The nicest way I can think of to do that is with separate parameters for each manipulator category: int i = convert::as<int>("+42", (_showpos=true, _base=ios::oct)); string s = convert::as<string>(123.456, (_scientific=true)); // or _float=ios::scientific ? Passing them in as a vector would as bad or worse and we've already decided against having to store them in a stateful converter. -Matt