Boost logo

Boost :

Subject: Re: [boost] [review] Conversion review starts today
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2011-09-04 05:04:27


On Sat, Sep 3, 2011 at 12:47 AM, Vicente J. Botet Escriba <
vicente.botet_at_[hidden]> wrote:

> Le 03/09/11 00:58, Jeffrey Lee Hellrung, Jr. a écrit :
>
>> On Fri, Aug 19, 2011 at 9:45 PM, Gordon Woodhull<gordon_at_[hidden]>**
>> wrote:
>>
>> * Do you think the library should be accepted as a Boost library? Be sure
>> to say this explicitly so that your other comments don't obscure your
>> overall opinion.
>>
>> To be honest, I'm very ambivalent. I'm hoping we can come to a consensus
>> on
>> whether this library is appropriate for Boost or not.
>>
>> Of course, "informal reviews" and discussion are also welcome.
>> Let me first say that the primary reason for deciding against outright
>> acceptance at the moment is purely philosophical and may be entirely
>> misguided. It seems to me that Conversion offers a generic solution to a
>> problem that rarely (if ever?) arises in generic contexts. This makes me
>> question its utility. Vicente, I would love to see an example where
>> Conversion solves a real conversion-between-unrelated-**types problem
>> (that
>> couldn't be solved in an equally simple or simpler way) within a generic
>> context; it's just difficult for me to imagine this, which might be
>> entirely
>> my own mental block problem.
>>
> My expectations were maybe simpler than yours. If two types T1 and T2
> provided by 3rd party libraries model the same concept, I want to be able to
> convert array<T1,N> and array<T2,N>. My motivating example was to find ugly
> one interface as
>
> array<time_t,N> tt_arr;
> array<chrono::timepoint<**system_clock,chrono::**milliseconds>,N> ctp_arr;
>
> ctp_arr =make_chrono_timepoint_system_**clock_milli_array(tt_arr);
>
> which will call to a function make_chrono_timepoint_system_**clock_milli
> for each one of the array elements.
>
> I have not needed to call to generic conversions inside other algorithms
> than implementing extrinsic convertions.
>

Sure, that makes sense and is indeed very reasonable.

Comming back to string<->type conversions. These kind of conversions can not
> be used with the library as a string and a type doesn't model the same
> concept. We need to interpret the string in a certain way to make an
> instance of a type and vice-versa. Coerce and Lexical Cast give some answers
> to this problem. One of my errors was to try to respond with my library to
> this problem through a generic conversion.
>

I agree. It is certainly much more reasonable to explicitly reduce the
scope of your library down to interconversions between types which are
somehow concept-related. As you've surmised, the big problem with string
<-> type conversions and similar is an absence of universal semantics.

An alternative I didn't considered while writing this library, as you and
> others have suggested, is passing a functor that knows how each one of the
> needed conversion can be performed. While this solves the ODR issue, it
> forces the user to build the functor which could not be an eassy task for an
> end user. I need to take sometime to experiment with this design in oder to
> see its advantages and liabilities.
>

Yes, I can imagine a lot of repeated boilerplate from multiple users
defining their own functors to do the same conversions. But I don't see any
other way around the ODR issue without outlining strict usage patterns
within the documentation of Conversion. I don't feel like Conversion's
framework is currently very scalable: at some point, a user will want to use
libraries C and D, each of which define conversions between typeA and
typeB. At best, this will be detected at compile time, but regardless,
you're hosed. Can we design Conversion to prevent this collision from
happening?

What if the framework defined by Conversion was less universal, and more
local to the library which wishes to utilize it? I know that suggestion is
very vague and I don't really have a good idea for what that would look
like. Maybe if we went strictly with conversion functors and Conversion
provides facilities to make such functors easy to define and use...?

 I think my perspective has been colored by my own experience in trying to
>> solve this problem. I, too, needed a framework within which to convert
>> unrelated (numeric) types, and built a framework similar (but, of course,
>> simpler) to what Conversion offers. Upon reevaluation, though, I
>> concluded
>> that this framework was too inflexible and a visitor-based solution would
>> be
>> more appropriate *for my application*. For me, I needed additional
>> *context* to convert between certain types, and I also wanted to support
>> the
>> flexibility of different conversion *implementations*. In applications
>> requiring conversions between unrelated types, context and varying
>> implementations seem to me to be features that would at least occasionally
>> be desired, and there isn't really a convenient way for Conversion to
>> support that. Sure, you can wrap your "from" objects to tag them to
>> select
>> the desired conversion implementation or to bundle them with the desired
>> context, but I wouldn't consider that very convenient and it certainly
>> reduces genericity (much better to have the implementation and context
>> dictated by the functor).
>>
> The kind of conversion I needed to apply didn't had any need of a context.
> I don't like the grap idea too much and I have not used it in concrete
> examples.
>

s/grap/wrap, I assume?

> When a context is needed, it is clear that we need a converter object as it
> is done for example on Boost.Numeric. There is the converter class which is
> able to store a context and make specific conversions and the numeric_cast
> function which uses a default converter.
>

Ah, okay.

> Aside from my philosophical objections, Conversion has the potential to
>> promote ODR violations, and this just seems like a Bad Thing. Sure, there
>> are other extendable operations (e.g., operator< or operator==) that
>> could
>> cause ODR violations if defined for unrelated types by some 3rd party, but
>> Conversion seems unique in the sense that it provides an extension point
>> for
>> an operation that *inherently* must operate with two unrelated types, with
>> the typical case that this operation is defined by some 3rd party
>> disassociated from the involved types. I don't think education is
>> sufficient to adequately mitigate this problem. But I don't know, maybe
>> I'm
>> taking a corner-case problem and blowing it up into a big issue...
>>
> Of course, I agree with the ODR violation promotion, and the library can't
> provide a clean mechanism to avoid it.
> I guess this will be at least useful to show that this kind of issue can be
> promoted by other libraries as well (e.g. libraries that need to make
> concept maps, ...)
>

Maybe the ODR issue can be solved with some "out-of-the-box" thinking...

- Jeff


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