
Hi all, Here is my review of the Conversion library. I like the idea of a uniform configurable casting operator, whether it's called convert_to, static_cast, convert_cast, or extrinsic_cast. If I had to write a conversion function, I would rather write it as an overload of a general-purpose converter, rather than giving it some ugly typeA2TypeB name. And I would rather find out what header to include and use a generic function rather than using such some specific name. I vote to accept the library (although obviously as Review Manager I'll follow the wishes of all reviewers). Part of the reason I took on the challenge of managing this review is that the library is something people don't know they need. I think uniformity of interface is a good enough reason to use the library, but when would you need a truly generic conversion function as this library offers? Or more to the point, what does it mean to have a "shadow conversion space" for types that don't know about each other? We would hope that libraries are generic enough so that their types can be adapted to work with each other (prime example: Polygon & Geometry). But it's the sad truth that most libraries are not designed this way, and any non-header library can't be designed this way. So that's where Conversion steps in to make combining those libraries cleaner. As we've already discussed, the Achille's Heel of this library is that it requires all compilation units to agree on what conversions they will use, to avoid ODR violations. In practice this probably means that users would have to maintain their own conversion setup headers, which is annoying. But it's hard to imagine an openly configurable global utility that doesn't suffer from some version of this problem. John Bytheway's suggestion of tagging libraries with type keys is an interesting idea. I think Vicente also mentioned the possibility of a scheme that would cause linker errors instead of ODR violations, which would be an improvement. (FWIW I suggested something involving #error but of course that would only work within a CU.) In my mind it is very clear that a templated function<T>(x) will probably return a T and I don't find it necessary that the proposed function has to use the preposition "to". But that's because I'm very aware that the explicit template argument must be the return type, which is understandably not clear to everyone. While the recursive features of this library look interesting and useful, I wonder if there isn't a more general way to do this. I keep thinking it's an awful lot like fusion::copy or Marsden's Traversals. Well, that's enough for now. I hope later today to post summaries of some comments I received off-list and maybe get those people to join the conversion. (You know who you are!) Cheers, Gordon

Gordon Woodhull wrote:
If I had to write a conversion function, I would rather write it as an overload of a general-purpose converter, rather than giving it some ugly typeA2TypeB name.
Why is e.g. rgb_to_cmyk() "ugly"? Is it because it is C, and C syntax is ancient history that must be purged from modern C++? Regards, Phil.

Le 30/08/11 00:09, Phil Endecott a écrit :
Gordon Woodhull wrote:
If I had to write a conversion function, I would rather write it as an overload of a general-purpose converter, rather than giving it some ugly typeA2TypeB name.
Why is e.g. rgb_to_cmyk() "ugly"?
Is it because it is C, and C syntax is ancient history that must be purged from modern C++?
Hi, I would not say ugly. Just that it needs some glue to be able to use it in a generic context. Vicente

Hi there, On Mon, Aug 29, 2011 at 6:30 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 30/08/11 00:09, Phil Endecott a écrit :
Gordon Woodhull wrote:
If I had to write a conversion function, I would rather write it as an overload of a general-purpose converter, rather than giving it some ugly typeA2TypeB name.
Why is e.g. rgb_to_cmyk() "ugly"?
GIL has such functionality. I like their way of structuring conversion. Regards, Christian

Hi Phil, On Aug 29, 2011, at 6:09 PM, "Phil Endecott" <spam_from_boost_dev@chezphil.org> wrote:
Gordon Woodhull wrote:
If I had to write a conversion function, I would rather write it as an overload of a general-purpose converter, rather than giving it some ugly typeA2TypeB name.
Why is e.g. rgb_to_cmyk() "ugly"?
Is it because it is C, and C syntax is ancient history that must be purged from modern C++?
I have nothing against C. (I have learned a few techniques from C that got lost in C++'s rush to object orientation.) It's probably a matter of personal taste, but once I know that a function is a conversion from X to Y any other names are just noise to me. Having a unique name means (to me) that there might be many other ways of doing the same thing, and I'm not sure if I've chosen the right one. Going through a generic function means I or someone has chosen the best way and can replace it if they want. E.g. convert strings to & fro types with a generic interface where you could switch in either lexical_cast or coerce and evaluate their performance. Granted this is not as strong an argument as if we had a real use case for generic conversion itself. E.g. why write template<typename X, typename Y> void do_something_amazing(Y const& Y) { X x; // If only I could convert Y to X... aha! x = boost::conversion::convert_to<X>(y); // ... some magic occurs } ? The only example I could come up with is implementing Perl-like scalars in C++ but I have no idea why you'd want to do that. So I'm hoping that some people who have tried to use lexical_cast for general type-to-type conversion will speak up. I think Vicente's argument is much like my "personal taste" argument above: he would just rather have a single function than many. Especially when you consider that there's combinatorial complexity in the number of interchangeable types. Cheers Gordon

On Aug 29, 2011, at 3:09 PM, Phil Endecott wrote:
Gordon Woodhull wrote:
If I had to write a conversion function, I would rather write it as an overload of a general-purpose converter, rather than giving it some ugly typeA2TypeB name.
Why is e.g. rgb_to_cmyk() "ugly"?
cmyk_t cmyk = rgb_to_cmyk( rgb ); That's why. Compare: cmyk_t cmyk = cmyk_from_rgb( rgb );
Is it because it is C, and C syntax is ancient history that must be purged from modern C++?
In the absence of parameterization in the caller (where the called function must be a template), a plain function has the advantage of looser coupling: You only need the function prototype in scope, whereas to call a function template you need to have the specialization, (each of) which in turn needs the template declaration. If you touch the header defining the template (or something else it includes), every user of every specialization needs to be recompiled. Then again, I'm biased, since one of the compilers I support sometimes refuses to inline functions when templates are involved, and larger include sets dramatically slow down compiling, because I/O is expensive. I agree with consistent naming, but I don't see <> and :: as inherently superior punctuation to _. Josh

On Wed, Aug 31, 2011 at 1:11 AM, Joshua Juran <jjuran@gmail.com> wrote:
On Aug 29, 2011, at 3:09 PM, Phil Endecott wrote:
Gordon Woodhull wrote:
If I had to write a conversion function, I would rather write it as an overload of a general-purpose converter, rather than giving it some ugly typeA2TypeB name.
Why is e.g. rgb_to_cmyk() "ugly"?
cmyk_t cmyk = rgb_to_cmyk( rgb );
That's why. Compare:
cmyk_t cmyk = cmyk_from_rgb( rgb );
Is it because it is C, and C syntax is ancient history that must be purged from modern C++?
In the absence of parameterization in the caller (where the called function must be a template), a plain function has the advantage of looser coupling: You only need the function prototype in scope, whereas to call a function template you need to have the specialization, (each of) which in turn needs the template declaration. If you touch the header defining the template (or something else it includes), every user of every specialization needs to be recompiled.
Then again, I'm biased, since one of the compilers I support sometimes refuses to inline functions when templates are involved, and larger include sets dramatically slow down compiling, because I/O is expensive.
I agree with consistent naming, but I don't see <> and :: as inherently superior punctuation to _.
To be fair, function templates can be specialized without defining a main template, and in that case you get the same amount of coupling as when you use regular functions. I do agree however that the call syntax should not rely on <>. One reason is that it turns off ADL. Another reason is that sometimes an implicit conversion to match an existing non-template overload is preferable to instantiating a template. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

On Aug 31, 2011, at 3:01 PM, Emil Dotchevski wrote:
To be fair, function templates can be specialized without defining a main template, and in that case you get the same amount of coupling as when you use regular functions.
I do agree however that the call syntax should not rely on <>. One reason is that it turns off ADL. Another reason is that sometimes an implicit conversion to match an existing non-template overload is preferable to instantiating a template.
The function overload customization point in Conversion uses a dummy parameter and no <>. convert_to<> is a just a more pleasant wrapper over that. So I think these language features are still available.

On Wed, Aug 31, 2011 at 1:13 PM, Gordon Woodhull <gordon@woodhull.com> wrote:
On Aug 31, 2011, at 3:01 PM, Emil Dotchevski wrote:
To be fair, function templates can be specialized without defining a main template, and in that case you get the same amount of coupling as when you use regular functions.
I do agree however that the call syntax should not rely on <>. One reason is that it turns off ADL. Another reason is that sometimes an implicit conversion to match an existing non-template overload is preferable to instantiating a template.
The function overload customization point in Conversion uses a dummy parameter and no <>. convert_to<> is a just a more pleasant wrapper over that. So I think these language features are still available.
What makes it more pleasant? Is it more convenient? In what use cases? Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

On Aug 31, 2011, at 5:11 PM, Emil Dotchevski wrote:
On Wed, Aug 31, 2011 at 1:13 PM, Gordon Woodhull <gordon@woodhull.com> wrote:
On Aug 31, 2011, at 3:01 PM, Emil Dotchevski wrote:
I do agree however that the call syntax should not rely on <>. One reason is that it turns off ADL. Another reason is that sometimes an implicit conversion to match an existing non-template overload is preferable to instantiating a template.
The function overload customization point in Conversion uses a dummy parameter and no <>. convert_to<> is a just a more pleasant wrapper over that. So I think these language features are still available.
What makes it more pleasant? Is it more convenient? In what use cases?
We are talking about a library that emulates overloading static_cast. The wrapper makes it look somewhat like static_cast<>(), whereas if you directly had to use the customization point it would be a mess: conversion::convert_to<Target>(source); versus explicit_convert_to(source, conversion::type_tag<Target>()) In other words, the ugliness is confined to the definition of conversions and doesn't spill over into their use. But the conversion definitions do get to benefit from ADL... actually I don't see how a conversion library could benefit from implicit conversions of the target type, but I might be missing something. Cheers, Gordon

On Wed, Aug 31, 2011 at 5:45 PM, Gordon Woodhull <gordon@woodhull.com> wrote:
On Aug 31, 2011, at 5:11 PM, Emil Dotchevski wrote:
On Wed, Aug 31, 2011 at 1:13 PM, Gordon Woodhull <gordon@woodhull.com> wrote:
On Aug 31, 2011, at 3:01 PM, Emil Dotchevski wrote:
I do agree however that the call syntax should not rely on <>. One reason is that it turns off ADL. Another reason is that sometimes an implicit conversion to match an existing non-template overload is preferable to instantiating a template.
The function overload customization point in Conversion uses a dummy parameter and no <>. convert_to<> is a just a more pleasant wrapper over that. So I think these language features are still available.
What makes it more pleasant? Is it more convenient? In what use cases?
We are talking about a library that emulates overloading static_cast. The wrapper makes it look somewhat like static_cast<>(), whereas if you directly had to use the customization point it would be a mess:
conversion::convert_to<Target>(source); versus explicit_convert_to(source, conversion::type_tag<Target>())
Ah. I'm not sure I like the fact that it is modeled after static_cast but I understand.
In other words, the ugliness is confined to the definition of conversions and doesn't spill over into their use. But the conversion definitions do get to benefit from ADL... actually I don't see how a conversion library could benefit from implicit conversions of the target type, but I might be missing something.
My point about ADL doesn't apply since the <> syntax is limited only to the point of the user calling convert_to, that is, as long as explicit_convert_to still uses ADL and it is not required to be a template, all is good. When I mentioned implicit conversions, I meant of the source type. Assuming the internals of convert_to<> do not require the actual conversion to be handled by templates, it is possible to define a small set of non-template overloads to handle a much larger set of input types that are already part of a carefully designed implicit conversion framework. If templates were required, the call to explicit_convert_to could instantiate a template instead of resorting to implicit conversion. I'm not saying that one is better than the other, only that both should be supported. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Le 01/09/11 03:15, Emil Dotchevski a écrit :
On Wed, Aug 31, 2011 at 5:45 PM, Gordon Woodhull<gordon@woodhull.com> wrote:
On Aug 31, 2011, at 5:11 PM, Emil Dotchevski wrote:
On Wed, Aug 31, 2011 at 1:13 PM, Gordon Woodhull<gordon@woodhull.com> wrote:
On Aug 31, 2011, at 3:01 PM, Emil Dotchevski wrote: In other words, the ugliness is confined to the definition of conversions and doesn't spill over into their use. But the conversion definitions do get to benefit from ADL... actually I don't see how a conversion library could benefit from implicit conversions of the target type, but I might be missing something. My point about ADL doesn't apply since the<> syntax is limited only to the point of the user calling convert_to, that is, as long as explicit_convert_to still uses ADL and it is not required to be a template, all is good.
When I mentioned implicit conversions, I meant of the source type. Assuming the internals of convert_to<> do not require the actual conversion to be handled by templates, This is the case. The behavior is similar to the obe of boost::swap.
boost::conversion::explicit_convert_to<Target>(source) calls explicit_convert_to(source, conversion::type_tag<Target>()) which could be overloaded.
it is possible to define a small set of non-template overloads to handle a much larger set of input types that are already part of a carefully designed implicit conversion framework. I don't know IIUC, when you use implicit, are you refering to predefined by the library? If yes, which conversion do you think that should belong to this set? If templates were required, the call to explicit_convert_to could instantiate a template instead of resorting to implicit conversion. I'm not saying that one is better than the other, only that both should be supported.
Here I'm lost. Best, Vicente

On Wed, Aug 31, 2011 at 11:10 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 01/09/11 03:15, Emil Dotchevski a écrit :
If templates were required, the call to explicit_convert_to could instantiate a template instead of resorting to implicit conversion. I'm not saying that one is better than the other, only that both should be supported.
Here I'm lost.
#include <iostream> int foo( int ) { return 1; } template <class T> int foo( T ) { return 2; } int main() { std::cout << foo(42L); } The presence of the template inhibits the implicit conversion of long to int. Sometimes this is desirable and sometimes it is not, and if the syntax used to call foo requires it to be a template, potentially useful implicit conversions can't kick in. I do understand that there is no such requirement in Conversion. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Joshua Juran wrote:
On Aug 29, 2011, at 3:09 PM, Phil Endecott wrote:
Gordon Woodhull wrote:
If I had to write a conversion function, I would rather write it as an overload of a general-purpose converter, rather than giving it some ugly typeA2TypeB name.
Why is e.g. rgb_to_cmyk() "ugly"?
cmyk_t cmyk = rgb_to_cmyk( rgb );
That's why. Compare:
cmyk_t cmyk = cmyk_from_rgb( rgb );
I prefer this: cmyk_t cmyk = to_cmyk(rgb); That permits reusing "to_cmyk" for various types via overloading. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com ________________________________ IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Stewart, Robert wrote:
Joshua Juran wrote:
On Aug 29, 2011, at 3:09 PM, Phil Endecott wrote:
Gordon Woodhull wrote:
If I had to write a conversion function, I would rather write it as an overload of a general-purpose converter, rather than giving it some ugly typeA2TypeB name.
Why is e.g. rgb_to_cmyk() "ugly"?
cmyk_t cmyk = rgb_to_cmyk( rgb );
That's why. Compare:
cmyk_t cmyk = cmyk_from_rgb( rgb );
I prefer this:
cmyk_t cmyk = to_cmyk(rgb);
That permits reusing "to_cmyk" for various types via overloading.
The problem with that is the (common?) case where rgb_t is a typedef for e.g. uint8_t[3]. This applies to other conversions too, e.g. time_t is a typedef for int, centigrade_t and farrenheit_t are both typedefs for float, etc. etc. Regards, Phil.

On Sep 2, 2011, at 12:14 PM, Phil Endecott wrote:
Stewart, Robert wrote:
Joshua Juran wrote:
On Aug 29, 2011, at 3:09 PM, Phil Endecott wrote:
Gordon Woodhull wrote:
If I had to write a conversion function, I would rather write it as an overload of a general-purpose converter, rather than giving it some ugly typeA2TypeB name.
Why is e.g. rgb_to_cmyk() "ugly"?
cmyk_t cmyk = rgb_to_cmyk( rgb );
That's why. Compare:
cmyk_t cmyk = cmyk_from_rgb( rgb );
I prefer this:
cmyk_t cmyk = to_cmyk(rgb);
That permits reusing "to_cmyk" for various types via overloading.
The problem with that is the (common?) case where rgb_t is a typedef for e.g. uint8_t[3]. This applies to other conversions too, e.g. time_t is a typedef for int, centigrade_t and farrenheit_t are both typedefs for float, etc. etc.
In a generic version you'd be forced to use Units or something to wrap those types before you ever saw them. This applies to any hypothetical converter code, as well as to the even more hypothetical (?) generic user code of Conversion. (So far we have a vague "Situations when generic conversion is required are less often" from Antony Polukhin, and a numeric application from Jeffrey Lee Hellrung.) I still find a syntax that emphasizes types over function names preferable, even if it involves a lot of angle brackets and ::'s. But I guess there's no disputing tastes, and we also saw a couple of technical problems with the approach taken in Boost.Conversion. Thanks everyone for participating. Cheers, Gordon

Le 02/09/11 19:41, Gordon Woodhull a écrit :
I still find a syntax that emphasizes types over function names preferable, even if it involves a lot of angle brackets and ::'s. But I guess there's no disputing tastes, and we also saw a couple of technical problems with the approach taken in Boost.Conversion.
Thanks everyone for participating.
Thanks to you also for your active participation, Vicente
participants (7)
-
Christian Henning
-
Emil Dotchevski
-
Gordon Woodhull
-
Joshua Juran
-
Phil Endecott
-
Stewart, Robert
-
Vicente J. Botet Escriba