If you want to write your own clip function, you can discover it and do something with it.
For example, suppose you want the clamp function to return by value if this is the only way to ensure that we don't get a broken link:
#include <type_traits> template<class A, class B, class C> constexpr std::conditional_t< std::is_lvalue_reference<A &&>::value && std::is_lvalue_reference<B &&>::value && std::is_lvalue_reference<C &&>::value, std::add_lvalue_reference_t<std::common_type_t<A, B, C>>, std::common_type_t<A, B, C> > clamp(A && value, B && min, C && max) { return value < min ? min : max < value ? max : value; }
This would make clamp(n, 0, 255)
effectively have the signature int clamp(int&, int&&, int&&)
; you will only get int & clamp(int&, int&, int&)
if all 3 inputs are lvalue references. Creating the returned const
link is trivial if you want it.
You can also not compile the function if they are not all lvalue references:
#include <type_traits> template<class A, class B, class C> constexpr std::add_lvalue_reference_t<std::common_type_t<A, B, C>> clamp(A && value, B && min, C && max) { static_assert(std::is_lvalue_reference<A &&>::value && std::is_lvalue_reference<B &&>::value && std::is_lvalue_reference<C &&>::value, ""); return value < min ? min : max < value ? max : value; }
source share