
Hi, the Boost.Range library introduce the concept of adaptor (or view). I'm wondering if this could be also convenient for the Boost.Convert library. Take the uuid user data type. uuid u; string res; u | corverted_to<string> | uppercased > res; The evaluation should be lazy, only when we assign throwg the > operator we force the evaluation. or string str; int i = str | radix(10) | locale(...) | converted_to<int>; Could this approach work for the Boost.Convert library? Best Vicente ----- Original Message ----- From: "Vladimir Batov" <batov@people.net.au> To: <boost@lists.boost.org> Sent: Saturday, February 28, 2009 2:37 PM Subject: Re: [boost] Boost.Convert+Boost.Parameter
From: "Andrey Semashev" <andrey.semashev@gmail.com> Just to restate my opinion, I don't quite like the "to" and "from" names. At least "from", in your notation, is confusing to me.
Yes, I remember. :-) We happen to like different things. So far I find to/from the cleanest of all the alternatives. Somehow you insist on
int i = convert<int>(str)
that in turn I do not find that great. ;-)
I don't understand what exactly you are trying to achieve. The conversion logic has to be concentrated somewhere,
The conversion logic for user-defined typed is often merely to provide op>> and op<< (as lexical_cast integrates user types). When one needs more, additional conversion logic is often concentrated in I/O Stream manipulators.
and I think it should be somewhere related to the source or the target type. In the nearby thread we were discussing conversion of user-defined types:
namespace user { struct uuid; }
user::uuid u; std::string str = convert::to< std::string >(u);
Do you plan to support this use case? How would you suggest the "casual user" to extend the conversion to
std::string str = convert::to< std::string >(u, uppercase_ = true);
Yes, it's is a typical case. All needed to have it integrated is to provide op>> and op<<. That is
std::ostream& operator<<(std::ostream& str, uuid const& id) { str << id.as_string(); return str; }
and a similar op>> get uuid integrated. I.e. nothing close to the complexity of your example. If you need additional (like "uppercase") configuration, one writes uppercase manipulator that will pass an additional parameter to op<<. Like
string s = convert::to<string>(uuid) >> uppercase;
std::ostream& operator<<(std::ostream& str, uuid const& id) { ...extract uppercase command from the stream... str << id.as_string(); return str; }
without support from the underlying conversion implementation for user::uuid?
unlike I/O Stream-based approach which allows the user to write his own manipulator and deploy it like
int i = convert::from(str, -1) >> my_special_formatter;
Do I understand correctly that the manipulators are used to format or parse the input by defining their streaming operators? If so, then how do the manipulators compose with each other? If I write:
int i = convert::from(str, -1) >> my_special_formatter >> my_super_special_formatter;
which one will be called?
They are called in the order or their appearance. Sometimes it matters, sometimes it does not. Like std::ws (enabled by default) needs to be first.
I think that the default value should be immediately recognizable. The default_ keyword does that. There were alternative syntax suggestions that provided that, too. I think, we should strive to the cleanest interface we can provide.
Oh, well, sounds great... but I am not sure. Feels like you are chasing that immediate recognize-ability a bit too hard. People somehow have survived without exlicitly naming every parameter and convert(str, -1) does not look the trickiest of all. And somehow you are not that concerned with the verbosity any more. I remember
boost::string::from(s, -1);
seemed long. Now
convert::from(s, default = -1);
does not seem that long at all. Nuh, that "immediate recognize-ability" pitch somehow does not stick with me. Sorry.
If you declare conversion functions with Boost.Parameter macros, you will be able to get rid of the inner parenthesis:
int i = convert::to<int>(str, radix_ = 10, locale_= ...); int i = convert::from(str, -1, radix_ = 10, locale_= ...);
Yes, I know. I am not that keen though... and does not it have some limit on the number of arguments?
That way the default value really gets lost in the arguments. So, unless we move to an alternative syntax, I'm for making it a named parameter as well:
int i = convert::from(str, default_ = -1, radix_ = 10, locale_= ...);
Yes, in this setting all parameters kinda asking for a name. A different style I guess. I am not sure it's growing on me. We'll see.