C++17 brought numerous long-awaited features and new algorithms. Even if you’ve never worked with image processing, it’s still likely that at some point you still had to ensure that some value stays within specific interval. This function is usually called clamp and C++17 introduced std::clamp that does exactly that.
Even though it’s trivial to implement, I usually try to use standard library algorithms whenever possible using it as a universal language for expressing intent in code. A few days I was about to use it yet another time, when suddenly I looked at its signature more carefully
template<class T>
constexpr const T& clamp( const T& v, const T& lo, const T& hi );
Note that all parameters are passed by const ref, which is known to cause extra moves due to potential aliasing. In my case, this function is used on huge tensors of floats so every instruction counts. To see what exactly are we talking about in terms of numbers, I’ve decided to compare performance of the quick-and-dirty version of clamp
and std::clamp using quick-bench:
And looks like our “fast” version is indeed faster, 5.6X faster, in fact:
The sad part is that our implementation is pretty much the same as the one used in std - the problem is in the API. There are many ways this API could have been improved - from “brute-force” overloads for built-in types that do not benefit from being passed by const ref, to using enable_ifs/contracts to use instantiations with pass-by-value semantics for “small” values and pass-by-reference for “large” ones.
Nothing is perfect and this article is no way discourages you from using standard library. In fact, I always encourage everyone to learn the things std has done right and mistakes we may want to avoid in our projects.
this is a good point. I did not realize the aliasing part until you pointed it out. since "&" are just addresses there is a need to take care of aliasing.
Are you talking about vectorization? If so would you mind to clarifying why aliasing is a problem while we dont have any write operation in std::clamp?