[review] conversion - Vladimir's comments

Hi Vicente, all, I had hoped that Vladimir Batov, author of Boost.Convert reviewed earlier this year, would contribute an "informal review". Instead I hope he doesn't mind if I quote some correspondence he sent off-list, and perhaps get him to join us. (I normally would never quote off-list communication on-list, but I don't see how a review manager can use off-list contributions without quoting them, if there's no request for anonymity. I hope Vladimir agrees that I've been judicious. ;) On Aug 1, 2011, at 8:47 PM, Vladimir Batov wrote:
On the conceptual level it is far from clear to me if such a framework is needed to begin with. In the Scope section Vicente explicitly states that his library "is not particularly concerned with cases of...". Those "excluded" cases happen to be the most tricky/used/needed cases. With those string-to-type, etc. cases taken out of the picture from the set-go, the usefulness of the remainder was many times questioned during Convert discussions (well before the Convert review) ... I never had a need for such a generic type-to-type conversion framework. Obviously, it's my own limited experience and it can be vastly different for others.
Secondly, on the implementation level I raised a few concerns in our conversations with Vicente about his library ... I do not feel Vicente's implementation is sufficiently generic. In particular, I am under strong impression that having Target and Source together as in
template< class Target, class Source > Target explicit_convert_to( Source const & u );
does not really work on a bigger scale. That does indeed work for *concrete* Target and Source types. However, when one tries to generalize (partially specialize) for a range of similar types, then I feel the framework easily falters. Namely, if I decide to specialize the above for a range of related Target types (say, string-related types) *and* separately specialize for a range of related Source types. Then compilation will fail if these two separate specializations happen to overlap for some Target-Source pair. That is not an academic case but concrete issues I faced with Convert. I'd expect it to be as relevant with Vicente's library.
I agree that it will take some careful shepherding to define a set of conversions without ambiguous overloads, which might be tricky to avoid if you're working with converters written by other people. Vicente, do you have any solutions for this? Cheers, Gordon

Le 30/08/11 17:44, Gordon Woodhull a écrit :
On Aug 1, 2011, at 8:47 PM, Vladimir Batov wrote:
Secondly, on the implementation level I raised a few concerns in our conversations with Vicente about his library ... I do not feel Vicente's implementation is sufficiently generic. In particular, I am under strong impression that having Target and Source together as in
template< class Target, class Source> Target explicit_convert_to( Source const& u );
does not really work on a bigger scale. That does indeed work for *concrete* Target and Source types. However, when one tries to generalize (partially specialize) for a range of similar types, then I feel the framework easily falters. Namely, if I decide to specialize the above for a range of related Target types (say, string-related types) *and* separately specialize for a range of related Source types. Then compilation will fail if these two separate specializations happen to overlap for some Target-Source pair. That is not an academic case but concrete issues I faced with Convert. I'd expect it to be as relevant with Vicente's library. I agree that it will take some careful shepherding to define a set of conversions without ambiguous overloads, which might be tricky to avoid if you're working with converters written by other people. Vicente, do you have any solutions for this?
Hi, I don't see how you can convert from some source to a conceptual range of target. Could you give me an example? The contrary is possible, i.e. we can convert from a conceptual range of Source to a concrete Target. I'm not saying that there is no case of overlaping specializations. Just the Vladimir case seems not a good example. Best, Vicente

On 30/08/2011 17:44, Gordon Woodhull wrote:
template< class Target, class Source> Target explicit_convert_to( Source const& u );
From the descriptions I have read, it seems this library is essentially those two lines. Why should two lines of basic and non-variable C++ code form a Boost library?
does not really work on a bigger scale. That does indeed work for *concrete* Target and Source types. However, when one tries to generalize (partially specialize) for a range of similar types, then I feel the framework easily falters. Namely, if I decide to specialize the above for a range of related Target types (say, string-related types) *and* separately specialize for a range of related Source types. Then compilation will fail if these two separate specializations happen to overlap for some Target-Source pair. That is not an academic case but concrete issues I faced with Convert. I'd expect it to be as relevant with Vicente's library.
An interesting point. You could use SFINAE, but that doesn't scale and requires all partial specializations to be mutually exclusive. I happen to have a library to solve the problem of specializing a function template for a category of types with best-match selection. It's essentially a formalized way to define tag hierarchies and macros to make n-ary tag dispatching transparent. It is what Boost.SIMD and NT2 use to manage their many specializations for different types and extensions. It will be proposed to Boost as a library of its own, named Boost.Dispatch. (sorry for hijacking the thread and advertising my stuff)

Le 30/08/11 19:20, Mathias Gaunard a écrit :
On 30/08/2011 17:44, Gordon Woodhull wrote:
template< class Target, class Source> Target explicit_convert_to( Source const& u );
From the descriptions I have read, it seems this library is essentially those two lines.
Why should two lines of basic and non-variable C++ code form a Boost library?
Hmm, well a little bit more than these two lines ;-)
does not really work on a bigger scale. That does indeed work for *concrete* Target and Source types. However, when one tries to generalize (partially specialize) for a range of similar types, then I feel the framework easily falters. Namely, if I decide to specialize the above for a range of related Target types (say, string-related types) *and* separately specialize for a range of related Source types. Then compilation will fail if these two separate specializations happen to overlap for some Target-Source pair. That is not an academic case but concrete issues I faced with Convert. I'd expect it to be as relevant with Vicente's library.
An interesting point. You could use SFINAE, but that doesn't scale and requires all partial specializations to be mutually exclusive.
Right. This doesn't mean that you can not use the library with specializations that don't conflict. Some useful examples are given for some Boost and STL classes. The idea is that the source and target specialization are enough concrete to avoid the conflict. If you have an example of partial specialization that will conflict I could try to see how I would do it.
I happen to have a library to solve the problem of specializing a function template for a category of types with best-match selection.
It's essentially a formalized way to define tag hierarchies and macros to make n-ary tag dispatching transparent.
It is what Boost.SIMD and NT2 use to manage their many specializations for different types and extensions.
It will be proposed to Boost as a library of its own, named Boost.Dispatch. (sorry for hijacking the thread and advertising my stuff)
No problem. I will use Boost.Dispatch if it responds to my needs. BTW, where can I get the Boost.Dispatch documentation? Best, Vicente

On 30/08/2011 19:38, Vicente J. Botet Escriba wrote:
Right. This doesn't mean that you can not use the library with specializations that don't conflict. Some useful examples are given for some Boost and STL classes. The idea is that the source and target specialization are enough concrete to avoid the conflict. If you have an example of partial specialization that will conflict I could try to see how I would do it.
Let's say I do a fusion sequence to string converter. Then I do a proto expression to string converter. (Proto expressions are also fusion sequences)
No problem. I will use Boost.Dispatch if it responds to my needs. BTW, where can I get the Boost.Dispatch documentation?
Not done yet. It's still in development and a bit rough around the edges.

Le 30/08/11 20:33, Mathias Gaunard a écrit :
On 30/08/2011 19:38, Vicente J. Botet Escriba wrote:
Right. This doesn't mean that you can not use the library with specializations that don't conflict. Some useful examples are given for some Boost and STL classes. The idea is that the source and target specialization are enough concrete to avoid the conflict. If you have an example of partial specialization that will conflict I could try to see how I would do it.
Let's say I do a fusion sequence to string converter. Then I do a proto expression to string converter.
(Proto expressions are also fusion sequences)
Your are right. This is a good example as it is not reasonable to make a specialization for fusion sequences that are no proto expressions. As any concept can be refined we need to use another technique than SFINAE to be able to specialize the refinement. Vicente

Le 30/08/11 22:30, Vicente J. Botet Escriba a écrit :
Le 30/08/11 20:33, Mathias Gaunard a écrit :
On 30/08/2011 19:38, Vicente J. Botet Escriba wrote:
Right. This doesn't mean that you can not use the library with specializations that don't conflict. Some useful examples are given for some Boost and STL classes. The idea is that the source and target specialization are enough concrete to avoid the conflict. If you have an example of partial specialization that will conflict I could try to see how I would do it.
Let's say I do a fusion sequence to string converter. Then I do a proto expression to string converter.
(Proto expressions are also fusion sequences)
Your are right. This is a good example as it is not reasonable to make a specialization for fusion sequences that are no proto expressions. As any concept can be refined we need to use another technique than SFINAE to be able to specialize the refinement.
Thinking about it a little but more, the library can take care of concepte refiniment specialization defining some wrapping classes for each concept. So we could have a fusion_sequence_wrapper and a proto_expression_wrapper that inherits from fusion_sequence_wrapper. Now we can define conversion specializations for fusion_sequence_wrapper<T> to string and fusion_sequence_wrapper<T> to string without using SFINAE. Of course, it will be better if the user didn't needed to wrap them explicitly. Vicente

Le 30/08/11 23:02, Vicente J. Botet Escriba a écrit :
Le 30/08/11 22:30, Vicente J. Botet Escriba a écrit :
Le 30/08/11 20:33, Mathias Gaunard a écrit :
On 30/08/2011 19:38, Vicente J. Botet Escriba wrote:
Right. This doesn't mean that you can not use the library with specializations that don't conflict. Some useful examples are given for some Boost and STL classes. The idea is that the source and target specialization are enough concrete to avoid the conflict. If you have an example of partial specialization that will conflict I could try to see how I would do it.
Let's say I do a fusion sequence to string converter. Then I do a proto expression to string converter.
(Proto expressions are also fusion sequences)
Your are right. This is a good example as it is not reasonable to make a specialization for fusion sequences that are no proto expressions. As any concept can be refined we need to use another technique than SFINAE to be able to specialize the refinement.
Thinking about it a little but more, the library can take care of concepte refiniment specialization defining some wrapping classes for each concept. So we could have a fusion_sequence_wrapper and a proto_expression_wrapper that inherits from fusion_sequence_wrapper.
Now we can define conversion specializations for fusion_sequence_wrapper<T> to string and fusion_sequence_wrapper<T> to string without using SFINAE. Of course, it will be better if the user didn't needed to wrap them explicitly.
P.S. There is a copy/paste typo in the last fusion_sequence_wrapper<T>. Please replace it by by proto_expression_wrapper<T>. Hi, I've found the motivation for the Dispatch library here (https://svn.boost.org/svn/boost/sandbox/SOC/2011/simd/libs/dispatch/doc/disp...). IIUC my wrappers could provide a solution that is close to the tag-dispatching mechanism. While the library present a generic framework that Boost.Conversion could use to avoid the SFINAE problem, it doesn't manage with the unique possible interpretation of the specialization. So I think your library could not be used in an open way where users can provide specializations and in this case SFINAE could be able to resolve the conflic as know all the specialized cases. Am I missing something? How Boost.Dispacth manage with this issue? What I mean is that any concept that could be mapped by the user, could be mapped by independent libraries that will be incompatible for a end user due to ODR violation signaled for Boost.Conversion. My question is, does it means that the library is not useful? Thanks for working on a general dispatch library, Vicente

On Aug 30, 2011, at 1:20 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
I happen to have a library to solve the problem of specializing a function template for a category of types with best-match selection.
It's essentially a formalized way to define tag hierarchies and macros to make n-ary tag dispatching transparent.
This sounds really neat! I look forward to it.

On Tue, Aug 30, 2011 at 8:44 AM, Gordon Woodhull <gordon@woodhull.com>wrote: [...]
On Aug 1, 2011, at 8:47 PM, Vladimir Batov wrote:
On the conceptual level it is far from clear to me if such a framework is needed to begin with. In the Scope section Vicente explicitly states that his library "is not particularly concerned with cases of...". Those "excluded" cases happen to be the most tricky/used/needed cases. With those string-to-type, etc. cases taken out of the picture from the set-go, the usefulness of the remainder was many times questioned during Convert discussions (well before the Convert review) ... I never had a need for such a generic type-to-type conversion framework. Obviously, it's my own limited experience and it can be vastly different for others.
[...snip implementation concerns...] It seems like Vladimir and I are partially echoing each other's concerns (see my response to Vicente's example real world use case). - Jeff

On Aug 1, 2011, at 8:47 PM, Vladimir Batov wrote:
On the conceptual level it is far from clear to me if such a framework is needed to begin with. In the Scope section Vicente explicitly states that his library "is not particularly concerned with cases of...". Those "excluded" cases happen to be the most tricky/used/needed cases. With those string-to-type, etc. cases taken out of the picture from the set-go, the usefulness of the remainder was many times questioned during Convert discussions (well before the Convert review) ... I never had a need for such a generic type-to-type conversion framework. Obviously, it's my own limited experience and it can be vastly different for others.
Vladimir's concerns resonate very well with my feelings towards Boost.Conversion. If I understand the spirit of the library right, it introduces a new concept with an associated operation, which can be used in generic algorithms. But I never needed such a thing and can't come up with a real-life example where I would use it. Roman Perepelitsa.
participants (5)
-
Gordon Woodhull
-
Jeffrey Lee Hellrung, Jr.
-
Mathias Gaunard
-
Roman Perepelitsa
-
Vicente J. Botet Escriba