[conversion] Motivation for two NEW generic conver_to and assign_to functions

Hi, I would like to share with you what motivated me to add two new free template functions convert_to<> and assign_to<> on the Boost.Conversion. I've needed recently to convert from boost::chrono::time_point<Clock, Duration> to boost::posix_time::ptime and from boost::chrono::duration<Rep, Period> to boost::posix_time::time_duration. This kind of conversions are needed quite often when you use code from two different libraries that have implemented the same concept using of course different representations and have hard coded the library interface to its own implementation. Well this is a normal situation, we can't avoid. Life is life. Quite often we need to convert unrelated types `Source` and `Target`. As these classes are unrelated, neither of them offers conversion operators to the other. Usually we get it by defining a specific function such as Target ConvertToTarget(Source& v); In my case I started by defining template <typename Rep, typename Period> boost::posix_time::time_duration convert_to_posix_time_time_duration( const boost::chrono::duration<Rep, Period>& from); template <typename Clock, typename Duration> posix_time::ptime convert_to_posix_time_ptime(const chrono::time_point<Clock, Duration>& from); Imagine now that you need to convert a `std::pair<Source, Source>` to a `std::pair<Target, Target>`. The standard defines conversions of pairs if the related types are C++ convertible: template <typename T1, typename T2> struct pair { ... template<class U, class V> //requires Constructible<T1, const U&> && Constructible<T2, const V&> std::pair(const pair<U, V>& p); template<class U , class V> //requires HasAssign<T1, const U&> && HasAssign<T2, const V&> std::pair& operator=(const std::pair<U , V>& p); ... }; But here the types Target and Source are not convertible other than using a specific function. Well we can again define a specific function std::pair<Target,Target> ConvertToPairOfTarget(std::pair<Source,Source>& v) { return std::make_pair(ConvertToTarget(v.fisrt), ConvertToTarget(v.second)); } While the `ConvertToTarget` could be specific, the `ConvertToPairOfTarget` should be generic template <typename Target1, typename Target2, typename Source1, typename Source2) std::pair<Target1,Target2> ConvertToPair(std::pair<Source1,Source2>& v); In order to do that we need that the pair template parameters define a common function, let it call `convert_to`: template <typename Target, typename Source) Target convert_to(Source& v); Thus `ConvertToPair` can be defined as template <typename Target1, typename Target2, typename Source1, typename Source2) std::pair<Target1,Target2> ConvertToPair(std::pair<Source1,Source2>& v) { return std::make_pair(convert_to<Target1>(v.fisrt), convert_to<Target2>(v.second)); } We need to specialize the `convert_to` function for the specific classes `Source` and `Target`. We can do it as follows template <> Target convert_to<Target, Source>(Source& v) {return ConvertToTarget(v);} In my case I need template <typename Rep, typename Period> boost::posix_time::time_duration convert_to<posix_time_time_duration, boost::chrono::duration<Rep, Period> > (const boost::chrono::duration<Rep, Period>& from) { return convert_to_posix_time_time_duration(from); } template <typename Clock, typename Duration> boost::posix_time::ptime convert_to<posix_time_ptime, chrono::time_point<Clock, Duration> > (const boost::chrono::time_point<Clock, Duration>& from) { return convert_to_posix_time_ptime(from); } So now I can convert std::pair<chrono::time_point<Clock, Duration>, boost::chrono::duration<Rep, Period> > to std::pair<boost::posix_time::ptime, boost::posix_time::time_duration> using the `ConvertToPair` function. What about converting `std::pair<Source,std::pair<Source,Source> >` to `std::pair<Target,std::pair<Target,Target> >`? The issue now is that `convert_to(std::make_pair<to, std::make_pair<to,to> >)` do not compiles because the conversion of `std::pair` is named `ConvertToPair`. So we need to specialize the function `convert_to` for pairs. template <typename T1, typename T2, typename S1, typename S2) static std::pair<T1,T2> convert_to<std::pair<Target1,T2>, std::pair<S1,S2> >( std::pair<Source1,Source2>& from) { { return std::pair<T1,T2>(convert_to<T1>(from.first), convert_to<T2>(from.second)); } There is still a last point. The preceding design works well with unrelated classes, but what about classes that already define some kind of conversion, using a constructor or a conversion operator. Do we need to make specialization for these conversion? The answer is no. We need just to define the default implementation of convert_to function to just return the explicit conversion. template < typename Target, typename Source> Target convert_to(const Source& from) { return Target(from); } With compilers supporting partial specialization of function templates there is no major problem. For the others, we need to use a trick; as it allows partial specialization of classes we can define convert_to by as relying to a specific function of a class, as follows: namespace partial_specialization_workaround { template < typename Target, typename Source > struct convert_to { static Target apply(const Source& val); }; } template < typename Target, typename Source > Target convert_to(const Source& val) { return partial_specialization_workaround::convert_to<Target,Source>::apply(val); } So now we can specialize `partial_specialization_workaround::convert_to` for pairs as follows: namespace partial_specialization_workaround { template <typename Target1, typename Target2, typename Source1, typename Source2) struct convert_to< std::pair<Target1,Target2>, std::pair<Source1,Source2> > { static std::pair<Target1,Target2> apply(std::pair<Source1,Source2>& v) { { return std::pair<T1,T2>(convert_to<T1>(from.first), convert_to<T2>(from.second)); } }; } Conclusion Classes or algorithms relying on a conversion by copy-construction or by the conversion operator can be made more generic by relaying in a function that explicitly states this conversion. Thus, instead of requiring Target(from) require convert_to<Target>(from) The same applies to classes or algorithms relying on the assignment operator. So instead of requiring to = from require assign_to(to, from); The default implementation of assign_to relies on the assignment operator template < typename Target, typename Source > To& assign_to(Target& to, const Source& from) { to = from; return to; } and with the workaround namespace partial_specialization_workaround { template < typename Target, typename Source > struct assign_to { static To& apply(Target& to, const Source& from) { to = from; return to; } }; } template < typename Target, typename Source > To& assign_to(Target& to, const Source& from) { return partial_specialization_workaround::assign_to<Target,Source>::apply(to, from); } For classes that are explicitly convertible and having a self assignment operator it is easy to make a specialization of assign_to as follows. to = convert_to<Target>(from); The rationale is that if there was not a copy constructor from a Source seems reasonable to think that there will not be an assignment operator. So in most of the cases, once we have specialized the convert_to function we recover a reasonable implementation for the assign_to function. When doing multiple assignments we use to do a = b = c; With assign_to we could do assign_to(a, assign_to(b, c)); and if we find this not really readable we can try with tie(a) = tie(b) = c; The behavior of tie recall the tie function of Boost.Tuple, but instead assigning multiple variable at once, assign only one by calling assign_to. So one of the advantages of using this common functions is uniformity. The other is that now we are able to find all the explicit conversions to one type, as we can do with explicit casts. We can even generalize this, so classes or algorithms relying on a member function, can be made more generic by relaying on a free function. The default function implementation could just call to the member function with the equivalent prototype, but this is out of the scope of this library. Note that this is already the case of the free functions as swap(), begin(), next(), end(), ... What about changing the C++ standard? C++1x has added explicit conversion operators, but they must always be defined in the Source class. The same applies to the assignment operator, it must be defined on the Target class. What it will interesting is to be able to add constructors and assignments operators to the class std::pair, so we can say that two pairs are convertible if the parameters are explicitly convertible using a convert_to function template<class U , class V> //requires HasConvertTo<T1, const U&> && HasConvertTo<T2, const V&> std::pair& operator=(const std::pair<U , V>& p) { return std::make_pair(convert_to<T1>(p.first), convert_to<T1>(p.second)); } But this is not possible. We can not add operators to a class from outside. A more generic alternative could be to make an evolution to the standard, so the convertible concept takes car of extrinsic conversions. We could be able to implicitly or explicitly add extrinsic conversion operators between unrelated types. Assignment operators could also be specialized. template < typename To, typename From > operator To(const From& val); template < typename To, typename From > To& operator=(To& to, const From& from); For example we could specialize the conversion from as chrono::time_point<Clock, Duration> to posix_time::ptime follows template < class Clock, class Duration> operator boost::posix_time::ptime(const boost::chrono::time_point<Clock, Duration>& from) { typedef boost::chrono::time_point<Clock, Duration> time_point_t; typedef boost::chrono::nanoseconds duration_t; typedef boost::duration_t::rep rep_t; rep_t d = boost::chrono::duration_cast<duration_t>(from.time_since_epoch()).count(); rep_t sec = d/1000000000; rep_t nsec = d%1000000000; return boost::posix_time::from_time_t(0)+ boost::posix_time::seconds(static_cast<long>(sec))+ boost::posix_time::nanoseconds(nsec); } The convert_to and the assign_to functions preted to be a library solution to the convertibility of unrelated types problem. Best regards, _____________________ Vicente Juan Botet Escribá

vicente.botet wrote:
Hi,
I would like to share with you what motivated me to add two new free template functions convert_to<> and assign_to<> on the Boost.Conversion.
<snip> This is a problem I've run across, too, of which I just have a basic framework in place that relies on finding a "convert" overload via ADL. I might have to read your docs and consider migrating to your specific implementation ;) Two comments (for now): 1) It's not uncommon that conversion to a "To" type from a "From" type needs more information than just an instance of a From. One example would be when dynamic memory allocation is necessary to construct the To type, e.g., when converting from a boost::array to a std::vector. In my application, I have to "upgrade" (i.e., convert) extended-but-fixed precision floats (which are statically allocated) to arbitrary precision floats (which are dynamically allocated), and the allocator_type of the arbitrary precision float shouldn't generally be default-constructed. I've worked around this by requiring my generic convert function to take a ConvertPolicy parameter (defaulted to some empty struct null_convert_policy_t), whose interpretation is up to the particular overload chosen for the conversion. I wouldn't mind seeing a better system in place. Have you considered this situation? 2) Assuming I understand the Conversion library correctly, what are the advantages to using both overloading via ADL and function template specialization as opposed to just the former? I'm not familiar of any other free functions used in boost (or anywhere else, for that matter) that rely on (perhaps I should say "allow"?) function template specialization, so I'm wondering what the motivation and pros/cons are (cons other than compiler support). I would guess that function template specializations must reside in the same namespace as the primary template...? This is definitely a problem that needs to be solved (correctly) in a generic fashion, so I'll try to follow your progress. - Jeff

----- Original Message ----- From: "Jeffrey Hellrung" <jhellrung@ucla.edu> To: <boost@lists.boost.org> Sent: Friday, October 23, 2009 10:07 PM Subject: Re: [boost] [conversion] Motivation for two NEW generic conver_to and assign_to functions
vicente.botet wrote:
Hi,
I would like to share with you what motivated me to add two new free template functions convert_to<> and assign_to<> on the Boost.Conversion.
<snip>
This is a problem I've run across, too, of which I just have a basic framework in place that relies on finding a "convert" overload via ADL. I might have to read your docs and consider migrating to your specific implementation ;)
Two comments (for now):
1) It's not uncommon that conversion to a "To" type from a "From" type needs more information than just an instance of a From. One example would be when dynamic memory allocation is necessary to construct the To type, e.g., when converting from a boost::array to a std::vector. In my application, I have to "upgrade" (i.e., convert) extended-but-fixed precision floats (which are statically allocated) to arbitrary precision floats (which are dynamically allocated), and the allocator_type of the arbitrary precision float shouldn't generally be default-constructed. I've worked around this by requiring my generic convert function to take a ConvertPolicy parameter (defaulted to some empty struct null_convert_policy_t), whose interpretation is up to the particular overload chosen for the conversion. I wouldn't mind seeing a better system in place. Have you considered this situation?
2) Assuming I understand the Conversion library correctly, what are the advantages to using both overloading via ADL and function template specialization as opposed to just the former? I'm not familiar of any other free functions used in boost (or anywhere else, for that matter) that rely on (perhaps I should say "allow"?) function template specialization, so I'm wondering what the motivation and pros/cons are (cons other than compiler support). I would guess that function template specializations must reside in the same namespace as the primary template...?
This is definitely a problem that needs to be solved (correctly) in a generic fashion, so I'll try to follow your progress.
- Jeff _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

----- Original Message ----- From: "Jeffrey Hellrung" <jhellrung@ucla.edu> To: <boost@lists.boost.org> Sent: Friday, October 23, 2009 10:07 PM Subject: Re: [boost] [conversion] Motivation for two NEW generic conver_to and assign_to functions
vicente.botet wrote:
Hi,
I would like to share with you what motivated me to add two new free template functions convert_to<> and assign_to<> on the Boost.Conversion.
<snip>
This is a problem I've run across, too, of which I just have a basic framework in place that relies on finding a "convert" overload via ADL. I might have to read your docs and consider migrating to your specific implementation ;)
Two comments (for now):
1) It's not uncommon that conversion to a "To" type from a "From" type needs more information than just an instance of a From. One example would be when dynamic memory allocation is necessary to construct the To type, e.g., when converting from a boost::array to a std::vector.
How do you know the To to which do you want to convert, if not given explictly?
In my application, I have to "upgrade" (i.e., convert) extended-but-fixed precision floats (which are statically allocated) to arbitrary precision floats (which are dynamically allocated), and the allocator_type of the arbitrary precision float shouldn't generally be default-constructed. I've worked around this by requiring my generic convert function to take a ConvertPolicy parameter (defaulted to some empty struct null_convert_policy_t), whose interpretation is up to the particular overload chosen for the conversion. I wouldn't mind seeing a better system in place. Have you considered this situation?
I'm interested on seen how you have solved the problem you found. and please could you post your example and show why it can not be specialized with the proposed convert_to or assign_to interface? Non conforming use case will improve the final library.
2) Assuming I understand the Conversion library correctly, what are the advantages to using both overloading via ADL and function template specialization as opposed to just the former? I'm not familiar of any other free functions used in boost (or anywhere else, for that matter) that rely on (perhaps I should say "allow"?) function template specialization, so I'm wondering what the motivation and pros/cons are (cons other than compiler support). I would guess that function template specializations must reside in the same namespace as the primary template...?
The single think I can answer is that the same question is already on the documentation, unfortuantley with no answer. The answer I can give you now is that I don't master ADL to the point of using it to imlement what I have in mind. I'm unable to saying you if this is possible or not. The question of using partial specializations of template functions is for the moment secondary, if there is a better way to achieve the same goal. My main concern is if we need the generic functions convert_to and assign_to. If this can be implemented in a better way using only ADL, we could do this way. Of course I'm intersted in knowing how this can be implemented using only ADL, even if this is evident for most of you.
This is definitely a problem that needs to be solved (correctly) in a generic fashion, so I'll try to follow your progress.
I'm open to any sugestion. If we can implement it using only ADL, I will do it once I'll know how. BTW, can we add functions on the 'std' namespace? Thanks for your comments and questions, Vicente

vicente.botet wrote:
Two comments (for now):
1) It's not uncommon that conversion to a "To" type from a "From" type needs more information than just an instance of a From. One example would be when dynamic memory allocation is necessary to construct the To type, e.g., when converting from a boost::array to a std::vector.
How do you know the To to which do you want to convert, if not given explictly?
It is given explicitly.
In my application, I have to "upgrade" (i.e., convert) extended-but-fixed precision floats (which are statically allocated) to arbitrary precision floats (which are dynamically allocated), and the allocator_type of the arbitrary precision float shouldn't generally be default-constructed. I've worked around this by requiring my generic convert function to take a ConvertPolicy parameter (defaulted to some empty struct null_convert_policy_t), whose interpretation is up to the particular overload chosen for the conversion. I wouldn't mind seeing a better system in place. Have you considered this situation?
I'm interested on seen how you have solved the problem you found. and please could you post your example and show why it can not be specialized with the proposed convert_to or assign_to interface? Non conforming use case will improve the final library.
I use overloads of the following signature: template< class From, class To, class ConvertPolicy > To convert(const From& from, type_tag<To>, const ConvertPolicy& convert_policy) struct type_tag is just an empty struct used to avoid having to provided the "To" template parameter explicitly. I thought maybe a function signature which didn't require explicit template parameters to call might be more ADL-friendly, but admittedly I have nothing to back this up with... For (one of) my specific use cases, I need to convert among user-defined numeric types, some of which are statically allocated and some of which are dynamically allocated. Or even a conversion from double to some dynamically-allocated numeric type might be desired. Either way, converting to a dynamically-allocated numeric type (think an arbitrary-precision rational) needs an allocator to construct it, so how would you convert a double to an arbitrary_precision_rational< T, allocator_type > without additionally providing an instance of allocator_type? To get around this issue, I ultimately pass an instance of the allocator_type as the ConvertPolicy parameter, and it is interpreted appropriately by the specific overload that implements the conversion from double to arbitrary_prec...< T, allocator_type >. Of course, this begs the question: How does the code that calls "convert" know to pass allocator_type as the ConvertPolicy? It generally doesn't, of course, so it also needs to be provided a ConvertPolicy parameter by *its* client. At some point up the call hierarchy (even if this has to be at main scope), it is known what family of types one needs to convert among, hence the appropriate ConvertPolicy would be known and initiated then. Is that an adequate explanation?
2) Assuming I understand the Conversion library correctly, what are the advantages to using both overloading via ADL and function template specialization as opposed to just the former? I'm not familiar of any other free functions used in boost (or anywhere else, for that matter) that rely on (perhaps I should say "allow"?) function template specialization, so I'm wondering what the motivation and pros/cons are (cons other than compiler support). I would guess that function template specializations must reside in the same namespace as the primary template...?
The single think I can answer is that the same question is already on the documentation, unfortuantley with no answer. The answer I can give you now is that I don't master ADL to the point of using it to imlement what I have in mind. I'm unable to saying you if this is possible or not. The question of using partial specializations of template functions is for the moment secondary, if there is a better way to achieve the same goal. My main concern is if we need the generic functions convert_to and assign_to. If this can be implemented in a better way using only ADL, we could do this way. Of course I'm intersted in knowing how this can be implemented using only ADL, even if this is evident for most of you.
This is definitely a problem that needs to be solved (correctly) in a generic fashion, so I'll try to follow your progress.
I'm open to any sugestion. If we can implement it using only ADL, I will do it once I'll know how.
You might want to read Herb Sutter's GotW articles on ADL, linked from Wikipedia: http://en.wikipedia.org/wiki/Argument_dependent_name_lookup
BTW, can we add functions on the 'std' namespace?
I've got the feeling that this is generally frowned upon, but not sure... :/
Thanks for your comments and questions, Vicente
No problem. - Jeff

Hi, ----- Original Message ----- From: "Jeffrey Hellrung" <jhellrung@ucla.edu> To: <boost@lists.boost.org> Sent: Saturday, October 24, 2009 9:53 PM Subject: Re: [boost] [conversion] Motivation for two NEW generic conver_to and assign_to functions
vicente.botet wrote:
Two comments (for now):
1) It's not uncommon that conversion to a "To" type from a "From" type needs more information than just an instance of a From. One example would be when dynamic memory allocation is necessary to construct the To type, e.g., when converting from a boost::array to a std::vector.
How do you know the To to which do you want to convert, if not given explictly?
It is given explicitly.
In my application, I have to "upgrade" (i.e., convert) extended-but-fixed precision floats (which are statically allocated) to arbitrary precision floats (which are dynamically allocated), and the allocator_type of the arbitrary precision float shouldn't generally be default-constructed. I've worked around this by requiring my generic convert function to take a ConvertPolicy parameter (defaulted to some empty struct null_convert_policy_t), whose interpretation is up to the particular overload chosen for the conversion. I wouldn't mind seeing a better system in place. Have you considered this situation?
I'm interested on seen how you have solved the problem you found. and please could you post your example and show why it can not be specialized with the proposed convert_to or assign_to interface? Non conforming use case will improve the final library.
I use overloads of the following signature:
template< class From, class To, class ConvertPolicy > To convert(const From& from, type_tag<To>, const ConvertPolicy& convert_policy)
struct type_tag is just an empty struct used to avoid having to provided the "To" template parameter explicitly. I thought maybe a function signature which didn't require explicit template parameters to call might be more ADL-friendly, but admittedly I have nothing to back this up with...
Do you mean that in order to use ADL you need to include the type_tag<To>?
For (one of) my specific use cases, I need to convert among user-defined numeric types, some of which are statically allocated and some of which are dynamically allocated. Or even a conversion from double to some dynamically-allocated numeric type might be desired. Either way, converting to a dynamically-allocated numeric type (think an arbitrary-precision rational) needs an allocator to construct it, so how would you convert a double to an arbitrary_precision_rational< T, allocator_type > without additionally providing an instance of allocator_type?
The convert function work well from converting one type in another. Well I would try wit this conversion arbitrary_precision_rational< T, allocator_type > convert_to<arbitrary_precision_rational< T, allocator_type >, std::pair<double, allocator_type > >( std::pair<double, allocator_type > from); And use it as double d; arbitrary_precision_rational< T, allocator_type > apr = convert_to<arbitrary_precision_rational< T, allocator_type > >(make_pair(d, allocator_type())); So the general case don't pay for the specific one. Do you find something wrong with this approach?
To get around this issue, I ultimately pass an instance of the allocator_type as the ConvertPolicy parameter, and it is interpreted appropriately by the specific overload that implements the conversion from double to arbitrary_prec...< T, allocator_type >.
Of course, this begs the question: How does the code that calls "convert" know to pass allocator_type as the ConvertPolicy? It generally doesn't, of course, so it also needs to be provided a ConvertPolicy parameter by *its* client. At some point up the call hierarchy (even if this has to be at main scope), it is known what family of types one needs to convert among, hence the appropriate ConvertPolicy would be known and initiated then.
Is that an adequate explanation?
Yes. I understand now your use case, and how you have solved it.
2) Assuming I understand the Conversion library correctly, what are the advantages to using both overloading via ADL and function template specialization as opposed to just the former? I'm not familiar of any other free functions used in boost (or anywhere else, for that matter) that rely on (perhaps I should say "allow"?) function template specialization, so I'm wondering what the motivation and pros/cons are (cons other than compiler support). I would guess that function template specializations must reside in the same namespace as the primary template...?
The single think I can answer is that the same question is already on the documentation, unfortuantley with no answer. The answer I can give you now is that I don't master ADL to the point of using it to imlement what I have in mind. I'm unable to saying you if this is possible or not. The question of using partial specializations of template functions is for the moment secondary, if there is a better way to achieve the same goal. My main concern is if we need the generic functions convert_to and assign_to. If this can be implemented in a better way using only ADL, we could do this way. Of course I'm intersted in knowing how this can be implemented using only ADL, even if this is evident for most of you.
This is definitely a problem that needs to be solved (correctly) in a generic fashion, so I'll try to follow your progress.
I'm open to any sugestion. If we can implement it using only ADL, I will do it once I'll know how.
You might want to read Herb Sutter's GotW articles on ADL, linked from Wikipedia:
Thanks for the pointer.
BTW, can we add functions on the 'std' namespace?
I've got the feeling that this is generally frowned upon, but not sure... :/
If it is not possible, how can ADL help to convert std::pair<A,B> to std::pair<C,D>? IMO, we need partial specialization to cover this case. I start to understand how ADL can simplify things. Maybe I can do as the bosst::swap function does. Either: * A function with the signature convert_to<Target>(Source const&) is available via argument dependent lookup Or: * A template specialization of boost::conversion::convert_to exists for Target and Source Or: * Target is copy constructible from Source (default implementation) namespace boost { namespace conversion { // include here my current implementation of convert_to template <typename Target, typename Source> Target convert_to(const Source& val) { return Target(from); } }} namespace boost_convert_to_impl { template <typename Target, typename Source> Target convert_to(Source const& from) { using namespace boost::conversion; //use boost::conversion::convert_to if ADL fails convert_to<Target>(from); } } namespace boost { template <typename Target, typename Source> Target convert_to(Source const& from) { ::boost_convert_to_impl::convert_to<To>(from); } } And use the tag_type<Target> trick if needed for ADL. Do you think that this interface is more satisfactory? Best, Vicente

Hi, ----- Original Message ----- From: "vicente.botet" <vicente.botet@wanadoo.fr> To: <boost@lists.boost.org> Sent: Saturday, October 24, 2009 11:01 PM Subject: Re: [boost] [conversion] Motivation for two NEW generic conver_toand assign_to functions
Hi, ----- Original Message ----- From: "Jeffrey Hellrung" <jhellrung@ucla.edu> To: <boost@lists.boost.org> Sent: Saturday, October 24, 2009 9:53 PM Subject: Re: [boost] [conversion] Motivation for two NEW generic conver_to and assign_to functions
vicente.botet wrote:
Two comments (for now):
1) It's not uncommon that conversion to a "To" type from a "From" type needs more information than just an instance of a From. One example would be when dynamic memory allocation is necessary to construct the To type, e.g., when converting from a boost::array to a std::vector.
How do you know the To to which do you want to convert, if not given explictly?
It is given explicitly.
In my application, I have to "upgrade" (i.e., convert) extended-but-fixed precision floats (which are statically allocated) to arbitrary precision floats (which are dynamically allocated), and the allocator_type of the arbitrary precision float shouldn't generally be default-constructed. I've worked around this by requiring my generic convert function to take a ConvertPolicy parameter (defaulted to some empty struct null_convert_policy_t), whose interpretation is up to the particular overload chosen for the conversion. I wouldn't mind seeing a better system in place. Have you considered this situation?
I'm interested on seen how you have solved the problem you found. and please could you post your example and show why it can not be specialized with the proposed convert_to or assign_to interface? Non conforming use case will improve the final library.
I use overloads of the following signature:
template< class From, class To, class ConvertPolicy > To convert(const From& from, type_tag<To>, const ConvertPolicy& convert_policy)
struct type_tag is just an empty struct used to avoid having to provided the "To" template parameter explicitly. I thought maybe a function signature which didn't require explicit template parameters to call might be more ADL-friendly, but admittedly I have nothing to back this up with...
Do you mean that in order to use ADL you need to include the type_tag<To>?
For (one of) my specific use cases, I need to convert among user-defined numeric types, some of which are statically allocated and some of which are dynamically allocated. Or even a conversion from double to some dynamically-allocated numeric type might be desired. Either way, converting to a dynamically-allocated numeric type (think an arbitrary-precision rational) needs an allocator to construct it, so how would you convert a double to an arbitrary_precision_rational< T, allocator_type > without additionally providing an instance of allocator_type?
The convert function work well from converting one type in another. Well I would try wit this conversion
arbitrary_precision_rational< T, allocator_type > convert_to<arbitrary_precision_rational< T, allocator_type >, std::pair<double, allocator_type > >( std::pair<double, allocator_type > from);
And use it as double d; arbitrary_precision_rational< T, allocator_type > apr = convert_to<arbitrary_precision_rational< T, allocator_type > >(make_pair(d, allocator_type()));
So the general case don't pay for the specific one. Do you find something wrong with this approach?
To get around this issue, I ultimately pass an instance of the allocator_type as the ConvertPolicy parameter, and it is interpreted appropriately by the specific overload that implements the conversion from double to arbitrary_prec...< T, allocator_type >.
Of course, this begs the question: How does the code that calls "convert" know to pass allocator_type as the ConvertPolicy? It generally doesn't, of course, so it also needs to be provided a ConvertPolicy parameter by *its* client. At some point up the call hierarchy (even if this has to be at main scope), it is known what family of types one needs to convert among, hence the appropriate ConvertPolicy would be known and initiated then.
Is that an adequate explanation?
Yes. I understand now your use case, and how you have solved it.
2) Assuming I understand the Conversion library correctly, what are the advantages to using both overloading via ADL and function template specialization as opposed to just the former? I'm not familiar of any other free functions used in boost (or anywhere else, for that matter) that rely on (perhaps I should say "allow"?) function template specialization, so I'm wondering what the motivation and pros/cons are (cons other than compiler support). I would guess that function template specializations must reside in the same namespace as the primary template...?
The single think I can answer is that the same question is already on the documentation, unfortuantley with no answer. The answer I can give you now is that I don't master ADL to the point of using it to imlement what I have in mind. I'm unable to saying you if this is possible or not. The question of using partial specializations of template functions is for the moment secondary, if there is a better way to achieve the same goal. My main concern is if we need the generic functions convert_to and assign_to. If this can be implemented in a better way using only ADL, we could do this way. Of course I'm intersted in knowing how this can be implemented using only ADL, even if this is evident for most of you.
This is definitely a problem that needs to be solved (correctly) in a generic fashion, so I'll try to follow your progress.
I'm open to any sugestion. If we can implement it using only ADL, I will do it once I'll know how.
You might want to read Herb Sutter's GotW articles on ADL, linked from Wikipedia:
Thanks for the pointer.
BTW, can we add functions on the 'std' namespace?
I've got the feeling that this is generally frowned upon, but not sure... :/
If it is not possible, how can ADL help to convert std::pair<A,B> to std::pair<C,D>? IMO, we need partial specialization to cover this case.
I start to understand how ADL can simplify things. Maybe I can do as the bosst::swap function does.
Either: * A function with the signature convert_to<Target>(Source const&) is available via argument dependent lookup Or: * A template specialization of boost::conversion::convert_to exists for Target and Source Or: * Target is copy constructible from Source (default implementation)
namespace boost { namespace conversion { // include here my current implementation of convert_to template <typename Target, typename Source> Target convert_to(const Source& val) { return Target(from); } }}
namespace boost_convert_to_impl { template <typename Target, typename Source> Target convert_to(Source const& from) { using namespace boost::conversion; //use boost::conversion::convert_to if ADL fails convert_to<Target>(from); } }
namespace boost { template <typename Target, typename Source> Target convert_to(Source const& from) { ::boost_convert_to_impl::convert_to<To>(from); } }
And use the tag_type<Target> trick if needed for ADL. Do you think that this interface is more satisfactory?
I have modified the convert_to implementation with your suggestions (see below) and now we can do: B b; A a1 (convert_to(b, type_tag<A>() )); The user can add overloading on the namespace of the class From, or specialize the boost::conversion::convert_to function. I have defined the tag with a defaulted parameter value type_tag<Target> tag=type_tag<Target>(), so we can also do A a1 (convert_to<A>(b)); I have added still an overloading to simplify some uses as a = convert_to(b, a); The Target parameter is not used other than to retrieve the type. template <typename Target, typename Source> Target convert_to(Source const& from, Target const&); What do you think? Does this interface satisfy your expectations? Best, Vicente _______________________________ namespace boost { template <typename T> struct type_tag {}; namespace conversion { template < typename To, typename From > To convert_to(const From& val, type_tag<To>) { return To(val); } } } namespace boost_conversion_impl { template <typename Target, typename Source> Target convert_to_impl(Source const& from) { using namespace boost::conversion; //use boost::conversion::convert_to if ADL fails return convert_to(from, boost::type_tag<Target>()); } } namespace boost { template <typename Target, typename Source> Target convert_to(Source const& from, type_tag<Target> tag=type_tag<Target>()) { return ::boost_conversion_impl::convert_to_impl<Target>(from); } template <typename Target, typename Source> Target convert_to(Source const& from, Target const&) { return ::boost_conversion_impl::convert_to_impl<Target>(from); } }

vicente.botet wrote:
Hi, <snip> I have modified the convert_to implementation with your suggestions (see below) and now we can do:
B b;
A a1 (convert_to(b, type_tag<A>() ));
The user can add overloading on the namespace of the class From, or specialize the boost::conversion::convert_to function.
I have defined the tag with a defaulted parameter value type_tag<Target> tag=type_tag<Target>(), so we can also do
A a1 (convert_to<A>(b));
I have added still an overloading to simplify some uses as
a = convert_to(b, a);
The Target parameter is not used other than to retrieve the type.
template <typename Target, typename Source> Target convert_to(Source const& from, Target const&);
What do you think? Does this interface satisfy your expectations?
Best, Vicente
That seems to be about what I had in mind originally. I think wrapping the ConvertPolicy (Target::allocator_type in my example) in with the Source parameter is a good idea, after some thought. My only additional suggestion (and perhaps I'm thinking about this wrongly) is to provide a special pair class for just such purposes. E.g., a convert_pack or conversion_pack or s/pack/pair/, which holds its member objects by reference and uses names more descriptive than "first" and "second". Wrapping everything up in a std::pair might create ambiguous overloads that convert from "actual" std::pair's, and it's also clearer what the source information actually consists of. Essentially, I'd like there to be a distinction between the "value information" (e.g., the number the object represents) and the "non-value information" (e.g., how the object dynamically allocates memory) within the Source. A couple of days ago John brought up some issues with using ADL exactly in this fashion, however. One suggested solution was to put an additional tag in the signature unique to the library implementing the conversion. I don't like this. I'm not sure how best to determine what that tag is suppose to be, and it adds seemingly unnecessary syntactic weight to the invocation of convert_to. It seems that somehow, 2 implementations of the same conversion operation need to be able to coexist. E.g., if we're converting from type1 in lib1 to type2 in lib2, we should prefer the convert_to overload in lib2 over the convert_to overload in lib1 (somehow), or vice versa. - Jeff

vicente.botet wrote:
I have modified the convert_to implementation with your suggestions (see below) and now we can do:
B b;
A a1 (convert_to(b, type_tag<A>() ));
The user can add overloading on the namespace of the class From, or specialize the boost::conversion::convert_to function.
I have defined the tag with a defaulted parameter value type_tag<Target> tag=type_tag<Target>(), so we can also do
A a1 (convert_to<A>(b));
This expansion of use cases will make the function more confusing and, I think, increase the opportunities to create ambiguities. I fail to understand why convert_to(b, type_tag<A>()) is acceptable and convert_to<A>(b) is not in any circumstance. The former is more verbose and both require the template parameter A. I understand that the former uses ADL to find the appropriate overload of a normal function, whereas the latter uses a function template specialization to define the function. I also understand that the former can appear in B's or A's namespace (or both!), whereas the latter must be in the boost::conversion namespace. What I don't understand is why the former is preferable to the latter, or why both are deemed necessary. For the latter version, the author of A, aware of B, could provide convert_to<A,B>() and the author of B could provide a generic version that might work for A, thus creating an ambiguity. Likewise, for the former variant, an overload could be declared in both A's and B's namespace. Thus, both approaches can lead to ambiguities, making neither better than the other. Indeed, supporting both would likely lead to even more chances for ambiguity.
I have added still an overloading to simplify some uses as
a = convert_to(b, a);
The Target parameter is not used other than to retrieve the type.
template <typename Target, typename Source> Target convert_to(Source const& from, Target const&);
That form doesn't make sense to me. If you already have an object of type Target to pass as the second argument, why not just use the following signature? template <typename Target, typename Source> void convert_to(Target & _dest, Source const & _from); That keeps the Target and Source values in the same order as the other variations (Target is on the lhs of the value-returning variations) and avoids the duplication of return value and argument. That function might be easier to use in some cases were it declared like this: template <typename Target, typename Source> Target & convert_to(Target & _dest, Source const & _from); (It would simply return _dest after assigning the converted value to _dest.) _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; 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:
I fail to understand why
convert_to(b, type_tag<A>())
is acceptable and
convert_to<A>(b)
is not in any circumstance.
For what it's worth, I strongly prefer the syntax of the latter -- it works just like the built-in new-style casts and boost::lexical_cast. --Jeffrey Bosboom

Hi, ----- Original Message ----- From: "Jeffrey Bosboom" <jbosboom@uci.edu> To: <boost@lists.boost.org> Sent: Monday, October 26, 2009 10:04 PM Subject: Re: [boost] [conversion] Motivation for two NEW generic conver_to and assign_to functions
Stewart, Robert wrote:
I fail to understand why
convert_to(b, type_tag<A>())
is acceptable and
convert_to<A>(b)
is not in any circumstance.
For what it's worth, I strongly prefer the syntax of the latter -- it works just like the built-in new-style casts and boost::lexical_cast.
Me too. The former is the extended form of the later. They are equivalent. The parameter type_tag<A> is there just to allow ADL. Both forms are allowed by the current implementation in Boost.Conversion. Best, Vicente

Hi Robert, ----- Original Message ----- From: "Stewart, Robert" <Robert.Stewart@sig.com> To: <boost@lists.boost.org> Sent: Monday, October 26, 2009 9:46 PM Subject: Re: [boost] [conversion] Motivation for two NEW genericconver_to and assign_to functions
vicente.botet wrote:
I have modified the convert_to implementation with your suggestions (see below) and now we can do:
B b;
A a1 (convert_to(b, type_tag<A>() ));
The user can add overloading on the namespace of the class From, or specialize the boost::conversion::convert_to function.
I have defined the tag with a defaulted parameter value type_tag<Target> tag=type_tag<Target>(), so we can also do
A a1 (convert_to<A>(b));
This expansion of use cases will make the function more confusing and, I think, increase the opportunities to create ambiguities.
I fail to understand why
convert_to(b, type_tag<A>())
is acceptable and
convert_to<A>(b)
is not in any circumstance.
The former is more verbose and both require the template parameter A.
I understand that the former uses ADL to find the appropriate overload of a normal function, whereas the latter uses a function template specialization to define the function. I also understand that the former can appear in B's or A's namespace (or both!), whereas the latter must be in the boost::conversion namespace. What I don't understand is why the former is preferable to the latter, or why both are deemed necessary.
Well, don't exactlly. The former uses ADL, but it seems to me quite extrange that the developer will add the overload in the Target namespace which has only a type_tag<Target> parameter. But of course this ambiguity is always possible. template <typename Target, typename Source> Target convert_to(Source const& from, type_tag<Target> tag=type_tag<Target>()) { return ::boost_conversion_impl::convert_to_impl<Target>(from); } The second case works because tag is a defaulted parameter. So there is no template specialization on the second case. convert_to<A>(b); is equivalent to convert_to(b, type_tag<A>()); Not a different think. The user need template specialization only if it can not add new function to the name space, as it is the case for the namespace std, isn't it? In this case we need to partialy specialize the nboost::conversion::convert_to function.
For the latter version, the author of A, aware of B, could provide convert_to<A,B>() and the author of B could provide a generic version that might work for A, thus creating an ambiguity. Likewise, for the former variant, an overload could be declared in both A's and B's namespace. Thus, both approaches can lead to ambiguities, making neither better than the other. Indeed, supporting both would likely lead to even more chances for ambiguity.
As I said there is no need to template specialization, if we can add an overload found by ADL. The main idea of convert_to is for unrelated libraries, neither of them will provide any conversion. But you are right, a developer would retrieve two definition of the same function done by two parties. Don't we have the same problem with a class A that doesnt provides a swap function, if two parties could specialize it and a third user could retrieve both definitions having an ambiguity?
I have added still an overloading to simplify some uses as
a = convert_to(b, a);
The Target parameter is not used other than to retrieve the type.
template <typename Target, typename Source> Target convert_to(Source const& from, Target const&);
That form doesn't make sense to me. If you already have an object of type Target to pass as the second argument, why not just use the following signature?
template <typename Target, typename Source> void convert_to(Target & _dest, Source const & _from);
You are righ. This was not a good idea.
That keeps the Target and Source values in the same order as the other variations (Target is on the lhs of the value-returning variations) and avoids the duplication of return value and argument.
That function might be easier to use in some cases were it declared like this:
template <typename Target, typename Source> Target & convert_to(Target & _dest, Source const & _from);
(It would simply return _dest after assigning the converted value to _dest.)
Boost.Conversion provides already a function assign_to with exactly this prototype. template <typename Target, typename Source> Target& assign_to(Target & _dest, Source const & _from); Note the difference, convert_to don't return by reference. I have prefered to name these two function differently. Is the following a valid overloading? template <typename Target, typename Source> Target convert_to(Source const& from, type_tag<Target> tag=type_tag<Target>()); template <typename Target, typename Source> Target& convert_to(Target & to, Source const & from); Thank you very much for your pertinent comment. I will add on the documentation this possible ambiguity, even if I have no mean to avoid it. Vicente

vicente.botet wrote:
----- Original Message ----- From: "Jeffrey Hellrung" <jhellrung@ucla.edu> To: <boost@lists.boost.org> Sent: Friday,
2) Assuming I understand the Conversion library correctly, what are the advantages to using both overloading via ADL and function template specialization as opposed to just the former? I'm not familiar of any other free functions used in boost (or anywhere else, for that matter) that rely on (perhaps I should say "allow"?) function template specialization, so I'm wondering what the motivation and pros/cons are (cons other than compiler support). I would guess that function template specializations must reside in the same namespace as the primary template...?
The single think I can answer is that the same question is already on the documentation, unfortuantley with no answer. The answer I can give you now is that I don't master ADL to the point of using it to imlement what I have in mind. I'm unable to saying you if this is possible or not. The question of using partial specializations of template functions is for the moment secondary,
There's no such thing as a partial specialization of a function template. Only classes may be partially specialized. You can explicitly specialize a function template (i.e. give specific values for all of its template parameters); is that what you mean?
if there is a better way to achieve the same goal. My main concern is if we need the generic functions convert_to and assign_to. If this can be implemented in a better way using only ADL, we could do this way. Of course I'm intersted in knowing how this can be implemented using only ADL, even if this is evident for most of you.
This is definitely a problem that needs to be solved (correctly) in a generic fashion, so I'll try to follow your progress.
I'm open to any sugestion. If we can implement it using only ADL, I will do it once I'll know how.
To do what you want with ADL has two problems: 1. You would have to call convert_to without passing any template arguments, so the destination type would have to be deducible from the arguments. You can use something like the type_tag Jeff mentioned. 2. The conversion function from A to B would have to be defined in either the namespace of A or of B (or of something else involved, e.g. the type_tag). If converting between types both from libraries you are not writing it is unwise to declare functions in their namespaces. If the library author decides to add support in the future with the same name (something I guess you're hoping for, if this name convert_to becomes widespread) then it will clash with your definition. But even if you avoid polluting other people's namespaces you will suffer a similar problem if they add a convert_to overload doing the same thing as yours; you'll get an ambiguous function call where you're using it. Worse still is if two people add convert_to overloads in the same namespace between the same types in such a way that the compiler doesn't see them both and complain; then you have an ODR violation and risk undefined behaviour (but you'll probably get away with a linking error). Similar issues apply even if you don't use ADL. The only ways I see to reliably avoid these sorts of problems are: 1. Whenever you want a conversion function between two types, get the author of a library containing one to add it to that library (and make sure the author of the other one doesn't add it to his). I presume this is impractical. 2. Somehow tag all the overloads and uses of convert_to in one library with a type from that library such that they will never clash with overloads from other libraries. The tag can facilitate ADL too. (This is a different tag from the type_tag above). This will add notational inconvenience and make it harder to use convert_to generically (e.g. as in your std::pair example; it will only work if there are convert_to overloads for both types in the pair with the same tag).
BTW, can we add functions on the 'std' namespace?
No, you may not. John Bytheway
participants (5)
-
Jeffrey Bosboom
-
Jeffrey Hellrung
-
John Bytheway
-
Stewart, Robert
-
vicente.botet