#include <algorithm>
#include <iostream>
#include <type_traits>
// T is value type,
// F is the type of a function that takes a T and returns a T
template<typename T, typename F>
class Clamped
{
public:
Clamped(T value, F func) : _func(func), _value(_func(value)) {}
// Some useful operator overload
// Assignment is probably wanted
Clamped<T, F>& operator=(const T& other) {
_value = _func(other);
return *this;
}
// Conversion to T operator
operator T() const {
return _value;
}
// Arithmetical operators, just one here for exemple
Clamped<T, F>& operator+=(const T& other) {
_value = _func(_value + other);
return *this;
}
private:
F _func;
T _value;
};
float clamp(float f)
{
if(f < -5.f) return -5.f;
else if(f > 5.f) return 5.f;
else return f;
}
int main()
{
auto clamp2 = [](float f){ return std::clamp(f, -6.f, 6.f); };
//Clamped<float, decltype(&clamp)> clamped_float(clamp);
// or
Clamped clamped_float(15.f, clamp2);
std::cout << clamped_float << std::endl; // Converts to float automatically
clamped_float = 10.f;
std::cout << clamped_float << std::endl;
clamped_float += 4;
std::cout << clamped_float << std::endl;
return 0;
}