
On Tue, May 31, 2011 at 1:06 PM, Vicente Botet <vicente.botet@wanadoo.fr>wrote:
Stewart, Robert wrote:
Vicente Botet wrote:
There is something that is troubling me on the fact that the developer will customize the conversion function using overload and ADL, but that the user could not take advantage in a simple way of this overloading. Taking in account that Boost.Conversion needs already a customization point to take care of conversion of types in the standard library (using partial specialization) the addition of the customization point using overload doesn't make simpler the user code, neither the developers customizing the class, as it would need to choose between two customization points that doesn't make any difference.
If no one find that the additional customization (via overloading) point add some benefit to the library, I will prefer to remove it. This will have the advantage of making the library quite more simple without limiting his expression power.
I have no idea to what you're referring. I've long since lost any notion of what overloads, customization points, etc. you're discussing. Can you show, with code, what the choices are and what problems you're
addressing?
Hi,
sorry I didn't give enough information.
Yes, thanks for this, I was wondering myself as well :) Currently Boost.Conversion has two customization points:
A- overloading of conversion::convert_to function
template (*typename Target, typename Source*) Target convert_to( Source const& from, dummy::base_tag<Target> const& p=dummy::base_tag(*Target*)());
The dummy parameter is there to allows overloading on the return type.
This signature of convert_to is *not* the signature that conversion::convert_to uses, right? I assume this is just the signature of the customization point. Also, is there a need for the second parameter to be defaulted? B- partial specialization of conversion::overload_workaround::convert_to
struct.
namespace overload_workaround { template (* typename To, typename From, class Enable = void *) struct convert_to { static To apply(const From& val); };
The default implementation of conversion::convert_to calls to an internal function that calls to convert_to (ADL) after introducing a default implementation (via using). If the user has defined an overload that is preferred to the default one, his overload is called. If there is no better overload the default one call the conversion::overload_workaround::convert_to::apply function, which by default returns Target(from).
The partial specialization part is needed as we can not add overload on the std namespace.
Fair enough.
When I introduced this complex mechanism I was expecting that the user could call the convert_to function without using the boost::conversion namesapce, but this is only true if it uses explicitly the dummy parameter, which doesn't seems natural to me.
I'm confused. You want the user to be able to call their own customization function directly without the use of a dummy parameter, by-passing boost::conversion::convert_to? I'm not sure I see the point... So if the user needs always to call the conversion function as follows
boost::conversion::convert_to(*T*)(v)
I don't see what's wrong with that...
Now, I don't see any advantages to maintain the customization point (A).
Well, (A) puts the customization within the user's namespace, while (B) requires opening the overload_workaround (or whatever) namespace. (A) only requires defining a function, while (B) requires specializing a struct and defining a member function. They both seem to achieve the same affect, but from the user's POV, (A) seems simpler. The customization point B alone allows to make whatever can be done with
both and it simplifies quite a lot the implementation.
"quite a lot" seems like a bit of an overstatement, although maybe you're speaking relative to the library as a whole. How much code accounts for the difference between allowing (A) and removing (A) altogether?
The default conversion::convert_to function needs just to call the customization point B.
Correct. The only thing (A) offers is (maybe) simplicity over (B).
I suspect that after refactoring, I will rename the namespace overload_workaround by something more positive. Any suggestions?
Or you could rename the convert_to struct to something else. Perhaps you should look in other Boost libraries to see how customization points are structured (Boost.MPL, Boost.Fusion, Boost.Spirit, and possibly Boost.Phoenix come to mind).
If you need more details of the current implementation, you can take a look at the header
http://svn.boost.org/svn/boost/sandbox/conversion/boost/conversion/convert_t... .
Hopping this would be clear for you now.
Thanks for your interest, Vicente
P.S. Sorry again for the angle brackets (* *)
One thing I wonder is: Suppose we have two classes from two different libraries, TypeA from LibraryA and TypeB from LibraryB, and we wish to define a conversion operation from TypeA to TypeB via Boost.Conversion. Does Boost.Conversion specify which library should contain this operation? I would suspect it couldn't, which makes me think there should be 2 levels of customization. For example, the first level of customization is defined by LibraryX when TypeX is the From type, and the second level of customization is defined by LibraryX when TypeX is the To type (X = A or B). Thus, if LibraryA provides a customization to convert TypeA to TypeB, but LibraryB likewise provides a customization to convert TypeA to TypeB, the customization in LibraryA is used unambiguously. - Jeff