Boost logo

Boost :

Subject: Re: [boost] Boost.Conversion review
From: John Bytheway (jbytheway+boost_at_[hidden])
Date: 2011-08-18 17:17:43


On 17/08/11 00:43, Vicente J. Botet Escriba wrote:
> Le 16/08/11 23:29, John Bytheway a écrit :
>> On 16/08/11 15:59, Gordon Woodhull wrote:
>>> Hi all,
>>>
>>> The review of Vicente Botet Escriba's Conversion library starts this
>>> Saturday August 20 and continues through August 29.
>>>
>>> This library provides a general system for type-to-type conversion.
>>> As such, it can be thought of either as a substitute for overloading
>>> static_cast, or as an alternative to lexical_cast when the
>>> intermediate conversion to text is not wanted.
>>>
>>> Your review and/or discussion would be greatly appreciated. As
>>> always, please post to the main Boost list if possible, or the
>>> boost-users list, or you can send your review directly to the Review
>>> Managers.
>> The primary concern I always have with libraries such as this one is
>> that they promote ODR violations. In particular, consider:
>>
>> library A defines type TA
>>
>> library B defines type TB
>>
>> library C defines a conversion from TA to TB
>>
>> library D defines a conversion from TA to TB
>>
>> Now libraries C and D are incompatible; they cannot both be used in the
>> same program without ODR violation.
> You are right and I have no solution to this big issue. I must add this
> to the documentation.
>
> I think that the same case appears when
>
> library T defines a trait type tt that must be specialized by the user.
> library A defines type TA
> library C needs to specialize the type trait tt for TA
> library D needs to specialize the type trait tt for TA
>
> Now libraries C and D are incompatible for the same reason.
>
> An organization could choose to organize his libraries in a way that
> make possible to avoid the odr in an easy way. But it is not simple to
> formalize some guidelines that can be shared between different
> organizations.
>
> I don't know, even if the following is not a solution to the issue,
> maybe the library could suggest to the library author defining the
> conversion to add a static variable that could be used to detect the odr
> violations at link time.
>
> I don't remember who, suggested that library C should define classes
> C::TA and C::TB inheriting from TA and TB so one knows the other and
> conversion can be defined intrinsicaly to these specific classes. I have
> not explored the usage, advantages and liabilities of this approach.

I once suggested a tag-dispatch system to help with an issue like this.
 It would go something like:

Boost.Conversion would define the base tag type boost::conversion::tag.

Library C would define C::tag, inheriting (probably virtually) from
boost::conversion::tag, and all the conversions it defines would be
marked somehow with this tag.

Similarly, library D would define D::tag, inheriting from
boost::conversion::tag.

If I write code that wishes to use conversions from both libraries (say
in program E) then I define E::tag, which inherits from A::tag and B::tag.

Then I do e.g.

TA a;
TB b = convert_to<TB>(a, E::tag());

The definition of convert_to is contrived such that if either C or D (or
Boost.Conversion) defines the conversion from TA to TB then it will
appear in the overload set as convert_to(A, C::tag) or convert_to(A,
D::tag) respectively, and thus be used. However, if they *both* do then
there will be an ambiguity in the function resolution because E::tag is
convertible to both C::tag and D::tag.

So, in summary, by sticking a library-specific tag type into all the
specializations and overloads defined by a library, we reduce the risk
of ODR violation (although it can still happen in a slightly more
obscure and indirect way). Furthermore, it automatically detects some
(depending on which headers were included, etc. etc.) situations where
there is disagreement about the implementation of the conversion and
turns it into a compiler error which (hopefully) makes the problem
somewhat clear.

One downside is that it's harder to write generic code using such
conversions; it would probably be necessary to have your caller provide
the appropriate tag type.

On balance I suspect this is not worth the trouble, but I just wanted to
throw the idea out.

John


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk