Boost logo

Boost :

Subject: Re: [boost] Conversion/Enums/Opaque request for interest
From: Wouter Van Alboom (wouter.vanalboom_at_[hidden])
Date: 2011-04-20 00:06:30

----- Original Message -----
From: "Vicente BOTET" <vicente.botet_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Saturday, April 16, 2011 1:43 PM
Subject: [boost] Conversion/Enums/Opaque request for interest

> Hi,
> Lastly I've been working on 3 Boost libraries proposals.
> * Boost.Conversion
> (,
> * Boost.Enums
> (
> * Boost.Opaque
> (
> Boost.Conversion manages with generic explicit conversion between
> unrelated types. The template function convert_to allows to convert a
> source type to a target type, using argument dependent lookup (ADL) to
> select a specialized convert_to function if available. If no specialized
> convert_to function is available, boost::conversion::convert_to is used.


I've done something similar to Boost.Conversion for (un)marschalling data to
some API.
Rather than template functions I was using structs, the ones that were
trivial were defined using some traits

template <class C__> struct CastMarshal;
template <> struct CastMarshal<char> { typedef int tyM; };
template <> struct CastMarshal<MyEnum> { typedef int tyM; };
template <> struct CastMarshal<int> { typedef int tyM; };

The conversions for them were done by the default definition of a template

template <class C__>
struct Marshal {
    typedef C__ tyU;
    typedef typename CastMarshal<C__>::tyM tyM;

    static tyM marshal(tyU pa) { return tyM(pa); }
    static tyU unmarshal(tyM pa) { return tyU(pa); }

You could write specialisations of this class for marshalling any type.

template <>
struct Marshal<Point> {
    typedef Point tyU;
    typedef std::pair<double,double> tyM;

    static tyM marshal(tyU const& pa) { ... }
    static tyU unmarshal(tyM const& pa) { ... }

I had also specialisations for containers like vector, map, pair, QMap,
QVector, ...
for example something like:

template <class C__,class A__>
struct Marshal<std::vector<C__,A__> > {
    typedef std::vector<C__,A__> tyU;
    typedef typename std::vector<Marshal<C__>::tyM,A__> tyM;

    static tyM marshal(tyU const& pa) { /* return vector with transformed
elements here */ }
    static tyU unmarshal(tyM const& pa) { /* return vector with transformed
elements here*/ }

So if I defined how to marshall types X and Y, I was able to marshall
QMap<X,vector<pair<Y,Y> > > and all other combinations as well.

I went even further and wrote templates that created function-adapters wich
did (un)marshalling of all parameters and the return-type.

char f1(map<char,char> const& paIn, vector<char>& paOut); // wanted
int f2(map<int,int> const& paIn, vector<int>& paOut); // signature with
marshalled types

I could define f1 as:

char f1(map<char,char> const& paIn, vector<char>& paOut)
     return MarshallParams(&f1,&f2)(paIn,paOut);

where MarshallParams was an overloaded templatefunction.
It checked if the transformed version of f1 had the same signature as f2,
and if so it returned a functor, otherwise it was a compile-error.
The returned functor marshalled the first parameter paIn and unmarshalled
the second parameter paOut (because in this case it was a rule that all
reference parameters were output parameters, not in-out parameters! So it
was useless in my case to do marshalling for non-const reference parameters,
as well as unmarshalling of const reference parameters.
If the corresponding types were identical like int to int then there was
also no need for (un)marshalling and the parameters could be passed
untransformed (by reference).
I did assume that all functions were no-throw.

For callbacks I had something similar but working in the other direction:
char f3(map<char,char> const& paIn, vector<char>& paOut); // my signature
int f4(map<int,int> const& paIn, vector<int>& paOut); // required signature

int f4(map<int,int> const& paIn, vector<int>& paOut);
     return UnmarshallParams(&f3,&f4)(paIn,paOut);


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