[Conversion] Practical applications

Dear Vicente & others, Would anyone like to share any practical or motivating applications for the proposed Boost.Conversion library? It seems to me that there are practical applications for particular types of conversion, e.g. T-to-string and string-to-T, and numeric casts, and serialisation. Apart from that, I am having trouble seeing practical reasons for generic conversion. A motivating case would be if a generic algorithm required conversion, but in the cases that I can think of either (a) the generic algorithm takes a functor, so the caller can pass the currently-required conversion as part of a lambda expression, or (b) you might need to select one of several possible conversions between a pair of types, which this library can't do, or (c) the algorithms are std:: ones which won't work with this library anyway. Example: struct person { string firstname; string surname; }; vector<person> people; // sorted by firstname // Try to find everyone with firstname "John": std::equal_range(people.begin(),people.end(),"John"); That doesn't work. Making it work has always struck me as more difficult than it should be. Can this library make it easier? If not, what similar problems can it help with? Regards, Phil.

Le 21/08/11 18:18, Phil Endecott a écrit :
Dear Vicente & others,
Would anyone like to share any practical or motivating applications for the proposed Boost.Conversion library?
It seems to me that there are practical applications for particular types of conversion, e.g. T-to-string and string-to-T, and numeric casts, and serialisation. Apart from that, I am having trouble seeing practical reasons for generic conversion. A motivating case would be if a generic algorithm required conversion, but in the cases that I can think of either (a) the generic algorithm takes a functor, so the caller can pass the currently-required conversion as part of a lambda expression, or (b) you might need to select one of several possible conversions between a pair of types, which this library can't do, or (c) the algorithms are std:: ones which won't work with this library anyway. Boost and the standard library defines conversion of containers of types that are explicitly convertible. For example std::pair defines the following
template <class T1, class T2> struct pair { ... template <class U, class V> pair(const pair<U,V>& p); } template<class U, class V> pair(const pair<U, V>& p); Requires: is_constructible<first_type, const U&>::value is true and is_constructible<second_- type, const V&>::value is true. Effects: Initializes members from the corresponding members of the argument. Remark: This constructor shall not participate in overload resolution unless const U& is implicitly convertible to first_type and const V& is implicitly convertible to second_type. If we can construct implicitly a pair from another pair of implicitly convertible types, why we couldn't allow the conversion from a pair of type that are extrinsically implicitly convertible to them? boost::array, std::tuple, and other know classes, define implicit or explicit constructors in a similar way. If you find these kind of conversion useful, maybe you could understand that we could extend it to types that were initialy designed by unrelated teams, but that one day are used by a 3rd needing conversion from one to the other. As part of my work, I use to be confronted to these kind of situations quite often, where 3rd party libraries we use convey "the same" kind of information following different and specific formats. Of course we can define specific functions to make the conversion between concrete types, but soon we need generic way to access to the conversion from generic Source and Target types. Boost.Conversion can be used to define all these conversions in a way that can be used with a uniform interface. It is not more :( Note that these conversion/transformations will not needed if the 3rd paty libraries provided a concept based interface, but in the real world we need to manage with libraries that have an important added value even if the interface is not of our taste. To resume: my intention with this library is to extend this possibility to conversions of unrelated types, containers of unrelated types, ... in a quasy-recursive way.
Example:
struct person { string firstname; string surname; };
vector<person> people; // sorted by firstname
// Try to find everyone with firstname "John": std::equal_range(people.begin(),people.end(),"John");
That doesn't work. Making it work has always struck me as more difficult than it should be. Can this library make it easier? If not, what similar problems can it help with?
No. The library is not intendeed to help in these cases. What you need is containers views. Thanks for your interest, Vicente

Vicente J. Botet Escriba wrote:
Le 21/08/11 18:18, Phil Endecott a ?crit :
Dear Vicente & others,
Would anyone like to share any practical or motivating applications for the proposed Boost.Conversion library?
It seems to me that there are practical applications for particular types of conversion, e.g. T-to-string and string-to-T, and numeric casts, and serialisation. Apart from that, I am having trouble seeing practical reasons for generic conversion. A motivating case would be if a generic algorithm required conversion, but in the cases that I can think of either (a) the generic algorithm takes a functor, so the caller can pass the currently-required conversion as part of a lambda expression, or (b) you might need to select one of several possible conversions between a pair of types, which this library can't do, or (c) the algorithms are std:: ones which won't work with this library anyway.
Boost and the standard library defines conversion of containers of types that are explicitly convertible. For example std::pair defines the following
template <class T1, class T2> struct pair { ... template <class U, class V> pair(const pair<U,V>& p); }
template<class U, class V> pair(const pair<U, V>& p); Requires: is_constructible<first_type, const U&>::value is true and is_constructible<second_- type, const V&>::value is true. Effects: Initializes members from the corresponding members of the argument. Remark: This constructor shall not participate in overload resolution unless const U& is implicitly convertible to first_type and const V& is implicitly convertible to second_type.
If we can construct implicitly a pair from another pair of implicitly convertible types, why we couldn't allow the conversion from a pair of type that are extrinsically implicitly convertible to them?
Right. But does your library make this possible? If you could change std::pair, you could change that ctor to call your new conversion function. But you can't change std::pair. Or, have I missed something? (I am looking at the "Motivation" section of your docs, where it shows 'T t = explicit_convert_to<T>(u);' and 'f(implicitly(u));', etc.)
As part of my work, I use to be confronted to these kind of situations quite often, where 3rd party libraries we use convey "the same" kind of information following different and specific formats.
It would be great to see some practical examples. Regards, Phil.

Le 22/08/11 22:50, Phil Endecott a écrit :
Vicente J. Botet Escriba wrote:
Le 21/08/11 18:18, Phil Endecott a ?crit :
Dear Vicente & others,
Would anyone like to share any practical or motivating applications for the proposed Boost.Conversion library?
It seems to me that there are practical applications for particular types of conversion, e.g. T-to-string and string-to-T, and numeric casts, and serialisation. Apart from that, I am having trouble seeing practical reasons for generic conversion. A motivating case would be if a generic algorithm required conversion, but in the cases that I can think of either (a) the generic algorithm takes a functor, so the caller can pass the currently-required conversion as part of a lambda expression, or (b) you might need to select one of several possible conversions between a pair of types, which this library can't do, or (c) the algorithms are std:: ones which won't work with this library anyway.
If we can construct implicitly a pair from another pair of implicitly convertible types, why we couldn't allow the conversion from a pair of type that are extrinsically implicitly convertible to them?
Right. But does your library make this possible? If you could change std::pair, you could change that ctor to call your new conversion function. But you can't change std::pair. Or, have I missed something? (I am looking at the "Motivation" section of your docs, where it shows 'T t = explicit_convert_to<T>(u);' and 'f(implicitly(u));', etc.)
The specialization of the customization point implicit_convert_cp allows to convert 'implicitly' pairs of extrinsicaly convertible types using the implicit_convert_to function. Now the user ca use the explicit_convert_to function to convert these types as for example B1 b1; B2 b2; std::pair<B1,B2> b; std::pair<A1,A2> a1(boost::conversion::explicit_convert_to<std::pair<A1,A2> >(b)); Note that implicit convertible implies explicit convertible. I wrote implicitly with coutes because we need to use a function which makes the call explicit. But with the function implicitly we are telling that the result is implicitly convertible to any type which is extrinsically implicit convertible. The multiple overload example show a morivating case on which the user can not use the implicit_convert_to<t> to mean an implicit conversion, as implicit conversions must be implicit. int f(int) { return 1; } int f(std::string const&) { return 2; } If a type T is extrinsically implicit convertible to int or std::string the following will work T v; std::cout << f(implicitly(v)) << " called" << std::endl; in the same way as if T were implicitly convertible to int or std::string the following is correct T v; std::cout << f(v) << " called" << std::endl; Resuming, the user wanting extrinsically implicit conversions, must use explicitly the 'implicitly' function.
As part of my work, I use to be confronted to these kind of situations quite often, where 3rd party libraries we use convey "the same" kind of information following different and specific formats.
It would be great to see some practical examples.
Yes, I know that the documentation is missing some practical examples. I have no access now to precise examples. I would try tomorrow to recover some more concrete examples and post them here. For the time been, let me show you a less concrete example: Imagine that library A defines struct T { int i; int j; }; and library B defines struct R { long x; long y; }; I magine now that you recover an array<T,3> from library A and that you need to use some functions in library B that need a c-array R[3]. If you stablish a conversion from T to R using convert_to and if you have that an array<T,N> can be assigned to an R[N] you could do the following array<T,3> source; // call some functions in A that fill this array A_f(source); //Now you need to present this data to the B library R target[3]; // convert source to target assign_to(target,source); // uses target in a B function B_g(target); We can think of the assign_to function as an algorithm that transform the source to the target using a 'functor' that calls to convert_to on its parts. In order to specialize this algorithm, the user needs to specialize the convert_to behavior instead of providing an explicit 'functor'. Note that we can not transform heterogeneous containers using a 'functor'. HTH, Vicente

Hi Vicente, Vicente J. Botet Escriba wrote:
Le 22/08/11 22:50, Phil Endecott a ?crit :
Vicente J. Botet Escriba wrote:
If we can construct implicitly a pair from another pair of implicitly convertible types, why we couldn't allow the conversion from a pair of type that are extrinsically implicitly convertible to them?
Right. But does your library make this possible?
The specialization of the customization point implicit_convert_cp allows to convert 'implicitly' pairs of extrinsicaly convertible types using the implicit_convert_to function. Now the user ca use the explicit_convert_to function to convert these types as for example
B1 b1; B2 b2; std::pair<B1,B2> b; std::pair<A1,A2> a1(boost::conversion::explicit_convert_to<std::pair<A1,A2> >(b));
Note that implicit convertible implies explicit convertible.
I wrote implicitly with coutes because we need to use a function which makes the call explicit.
Resuming, the user wanting extrinsically implicit conversions, must use explicitly the 'implicitly' function.
I was really hoping that I had misunderstood something and that actually your library could make it possible to have extrinsic implicit conversions. But it doesn't; the conversions still require additional syntax. So they aren't implicit conversions. Since you can't add this additional syntax to e.g. the std:: algorithms, I am still struggling to see how the library is useful.
Imagine that library A defines
struct T { int i; int j; };
and library B defines
struct R { long x; long y; };
I magine now that you recover an array<T,3> from library A and that you need to use some functions in library B that need a c-array R[3].
If you stablish a conversion from T to R using convert_to and if you have that an array<T,N> can be assigned to an R[N] you could do the following
array<T,3> source; // call some functions in A that fill this array
A_f(source);
//Now you need to present this data to the B library R target[3];
// convert source to target assign_to(target,source);
// uses target in a B function
B_g(target);
Or you could just: array<T,3> source; A_f(source); R target[3]; std::transform(source.begin(),source.end(),target,&R_to_T); B_g(target); where R_to_T is the same conversion function that you need - but with the advantage that I can define multiple conversions between each pair of types, if I want to. Regards, Phil.

Le 23/08/11 19:05, Phil Endecott a écrit :
Hi Vicente,
Vicente J. Botet Escriba wrote:
Le 22/08/11 22:50, Phil Endecott a ?crit :
Vicente J. Botet Escriba wrote:
If we can construct implicitly a pair from another pair of implicitly convertible types, why we couldn't allow the conversion from a pair of type that are extrinsically implicitly convertible to them?
Right. But does your library make this possible?
The specialization of the customization point implicit_convert_cp allows to convert 'implicitly' pairs of extrinsicaly convertible types using the implicit_convert_to function. Now the user ca use the explicit_convert_to function to convert these types as for example
B1 b1; B2 b2; std::pair<B1,B2> b; std::pair<A1,A2> a1(boost::conversion::explicit_convert_to<std::pair<A1,A2> >(b));
Note that implicit convertible implies explicit convertible.
I wrote implicitly with coutes because we need to use a function which makes the call explicit.
Resuming, the user wanting extrinsically implicit conversions, must use explicitly the 'implicitly' function.
I was really hoping that I had misunderstood something and that actually your library could make it possible to have extrinsic implicit conversions. But it doesn't; the conversions still require additional syntax. So they aren't implicit conversions.
Strinctly speaking not. But implicitly(s) is extrinsicaly implicitly convertible. It is something similar as how ref(x) is not a reference to x, but can be used to transport a reference, which is enough useful.
Since you can't add this additional syntax to e.g. the std:: algorithms, I am still struggling to see how the library is useful.
We can add them whereever we consider is useful to Boost.Containers (of course the last word is to Ion). Note that we can define also conversion between containers extrinsically. Best, Vicente

Phil Endecott <spam_from_boost_dev <at> chezphil.org> writes:
Would anyone like to share any practical or motivating applications for the proposed Boost.Conversion library?
I cannot answer for the advanced use, but we are definitely interested in a fast (locale independent) conversion from int/long/double to string. The good old sprintf seems to beat the stringstream by a factor 2. This is important when you do a large export (e.g. million data points) to csv or Excel (e.g. export drops then from 20 minutes to 10 minutes).

On Aug 24, 2011, at 8:36 AM, gast128 <gast128@hotmail.com> wrote:
I cannot answer for the advanced use, but we are definitely interested in a fast (locale independent) conversion from int/long/double to string.
Conversion isn't about string <-> type. You should try the proposed Coerce library for fast string <-> type conversions, esp if you are willing to spare some compile time in exchange.

Gordon Woodhull <gordon <at> woodhull.com> writes:
On Aug 24, 2011, at 8:36 AM, gast128 <gast128 <at> hotmail.com> wrote:
Conversion isn't about string <-> type. You should try the proposed Coerce library for fast string <-> type conversions, esp if you are willing to spare some compile time in exchange.
Ah I see now, having scanned the documentation. The original post mentioned something that it would support T <-> string. To answer the original question: I have no practical use for this library. But then again, it is probably most useful for (templated-) library writers. 2 side remarks: 1) Do i correctly understand that there will be 3 Boost libraries dealing with string conversion (Boost.Convert, Coerce, lexical_cast). 2) I get constantly 'You have lines longer than 80 characters. Fix that.' when posting from gmane.

On Aug 24, 2011, at 11:31 AM, gast128 <gast128@hotmail.com> wrote:
The original post mentioned something that it would support T <-> string.
I think Phil was arguing that there are uses for specific conversions like T <-> string but he didn't see the purpose of generic conversions as this library offers.
Do i correctly understand that there will be 3 Boost libraries dealing with string conversion (Boost.Convert, Coerce, lexical_cast).
Convert was withdrawn. Coerce is a speedy-runtime slower-compiling Spirit-based solution, and lexical_cast uses std::iostream.

On 24 August 2011 23:25, gast128 <gast128@hotmail.com> wrote:
lexical_cast uses std::iostream. Yes we noticed. It has a pretty easy interface, but unfortunately it has the previous mentioned performance drawbacks.
We will have a look at Coerce when it gets released.
Coerce can be found at http://svn.boost.org/svn/boost/sandbox/coerce/ and a copy of the in-progress documentation at http://vexocide.org/coerce/. The API should now be stable enough to use in production. Any and all feedback is welcome, please don't hesitate to contact me with questions. Kind regards, Jeroen

On 8/24/2011 7:34 PM, Jeroen Habraken wrote:
On 24 August 2011 23:25, gast128<gast128@hotmail.com> wrote:
lexical_cast uses std::iostream. Yes we noticed. It has a pretty easy interface, but unfortunately it has the previous mentioned performance drawbacks.
We will have a look at Coerce when it gets released.
Coerce can be found at http://svn.boost.org/svn/boost/sandbox/coerce/ and a copy of the in-progress documentation at http://vexocide.org/coerce/. The API should now be stable enough to use in production. Any and all feedback is welcome, please don't hesitate to contact me with questions.
You should have buildable docs as part of the sandbox distribution. It is not that hard to do given that you have quickbook files. Look at other sandbox diectories for how to set it up ( my own VMD or TTI can show you how ), or look at other Boost libraries for how to set it up.
participants (6)
-
Edward Diener
-
gast128
-
Gordon Woodhull
-
Jeroen Habraken
-
Phil Endecott
-
Vicente J. Botet Escriba