Boost logo

Boost :

Subject: Re: [boost] [conversion] ADL and templates
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2011-05-31 18:29:53

On Tue, May 31, 2011 at 1:06 PM, Vicente Botet <vicente.botet_at_[hidden]>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
> .
> 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

Boost list run by bdawes at, gregod at, cpdaniel at, john at