Boost logo

Boost :

From: Paul Mensonides (pmenso57_at_[hidden])
Date: 2006-08-31 17:05:20


 

> -----Original Message-----
> From: boost-bounces_at_[hidden]
> [mailto:boost-bounces_at_[hidden]] On Behalf Of Paul Mensonides

Revisions inline...

> You need a forwarding contructor on the 'data' structure to
> directly initialize the 'value' member. You also need a
> forwarding function on whatever takes the arguments from
> clients--so the resulting syntax looks something like:

Actually, you only need combinatorial forwarding on the function that takes
arguments from the client. You don't need it elsewhere because then you don't
have temporaries.

> smart_ptr<X> p = make_ptr<X>(a, b, 123);
>
> The make_ptr<X> function has to construct a
> 'smart_ptr<X>::data' object and initialize a smart_ptr with
> it and return that smart_ptr.
>
> One problem of forwarding is arity (which can be more-or-less
> solved with code generation). The more stubborn problem with
> forwarding is temporaries. They cannot be bound to a
> non-const reference, and the template mechanism cannot deduce
> T as const U in a parameter of type T&. OTOH,
> non-temporaries don't have any problem deducing T as U or
> const U in a parameter of type T&.
> Unfortunately, the only way to handle it transparently is to
> overload via cv-qualifier--which leads the the combinatorial
> explosion when multiple parameters are involved.

Given the above, you could solve (i.e. avoid) the combinatorial problem by
linearizing the input. If you have no temporaries, you can just use T& and T
will bind correctly to a cv-qualified type. To get rid of temporaries (which
can't bind to T&) you need:

template<class T> inline T& identity(T& x) {
    return x;
}
template<class T> inline const T& identity(const T& x) {
    return x;
}
template<class T> inline volatile T& identity(volatile T& x) {
    return x;
}
template<class T> inline const volatile T& identity(const volatile T& x) {
    return x;
}

What was called before as

f(a, b, c);

can be called as

f(identity(a), identity(b), identity(c));

...which is relatively easily generated via the preprocessor--especially with
variadic macros:

F(a, b, c) -> f(identity(a), identity(b), identity(c))

Without variadic macros, you'd have to specify the number of arguments or do
something like:

F((a)(b)(c))

Regards,
Paul Mensonides


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