
Le 26/09/11 20:01, Stewart, Robert a écrit :
Vicente J. Botet Escriba wrote:
Le 26/09/11 13:36, Dave Abrahams a écrit :
Note: you can solve that problem by asking the caller to do the conversion ;-)
I'm not sure this could always be the desired interface for the caller. When I want to clip an 22 bit integer to a 16 bit integer, I expect the result be a 16 bit integer. So in these cases the result type will be the types of lo and hi.
int v; short lo,hi; short res= clamp(v, lo,hi); How does the algorithm select the smaller return type when clamping to a limit, while selecting the larger return type otherwise? Well, maybe clamp shouldn't return the clamp-ed's type, but the bound's type. We could see the clamp function as a conversion limiting the valid values.
And in this case I can not convert the 22 bits integer to a 16 bit because I would lost some essential information.
short res= clamp(short(v), lo,hi); // not the expected // behavior That's the caller's fault, of course. I agree.
That means that I will need to convert to the
short res= short(clamp(v, int(lo),int(hi))); Right, but all of the information is visible to the caller.
You could also do that like this:
clamp<int>(v, lo, hi)
This force the bound type to be implicitly convertible to the clamp-ed type and the clamped type to be implicitly convertible to the result type. short res =clamp<int>(v,lo,hi);
For comparison with v, lo and hi must be promoted anyway, so the three-type version doesn't help. Forcing the caller to disambiguate isn't so bad, at least in this case.
An other possibility is to pass of the return type as template parameter: short res = clamp<short>(v,lo,hi); Note that in this particular case the single conversion is done when lo<v<hi and in this case it is safe as in the range. The interface with 3 types could be template <typename Res, typename T, typename Lo, Typename Hi> Res clamp(const &T, const &Lo, const &Hi); The constraint here would be that T, Hi, and Lo are explicitly convertible to Res. Vicente