I am using an an API that takes a function with a single argument as a callback. The callback takes a single argument of a certain type, and for simplicity, I'll say it returns a bool
. The main thing I was trying to put together was a range checking function. My intuition would be to write something like this:
template<class T, T min, T max>
constexpr bool in_range(T val) {
return (val >= min && val <= max);
}
static_assert(in_range<float, 0.0f, 1.0f>(0.5f), "doesn't work")
However, that doesn't work, so I defaulted to creating a function this way.
template<class T>
std::function<bool(T)> in_range(T min, T max) {
auto test = [min, max](T val) {
return (val >= min && val <= max);
};
return test;
}
assert(in_range<float>(0.0f, 1.0f)(0.5f))
Is there a way to write the function more in the form of the first function, so I'm not depending on std::function
and lambdas generated at runtime?
As floats aren't allowed as template non-type parameters, you'd have to take them as actual function arguments rather than template parameters.
If you want to have a function which only takes one argument, you can avoid the cost of the std::function
by returning the lambda directly. If we were using C++14, you could just make it return auto
:
template<class T>
auto in_range(T min, T max) { // Note: could be `constexpr` in C++17
return [min, max](T val) {
return (val >= min && val <= max);
};
}
However, since you are using C++11, you'd have to write out the callable type manually:
template <typename T>
class InRange {
public:
constexpr InRange(T min, T max)
: min(std::move(min))
, max(std::move(max))
{}
constexpr bool operator()(T const& val) const {
return (val >= min && val <= max);
}
private:
T min;
T max;
};
template<class T>
constexpr InRange<T> in_range(T min, T max) {
return InRange<T>(std::move(min), std::move(max));
}
Is there a way to write the function more in the form of the first function, so I'm not depending on std::function and lambdas generated at runtime?
If you can pass static global variables as template argument instead of float
literals, you can pass they by reference
Something as follows
#include <iostream>
template <typename T, T const & min, T const & max>
constexpr bool in_range (T val)
{ return (val >= min && val <= max); }
static constexpr float f0 { 0.0f };
static constexpr float f1 { 1.0f };
int main ()
{
static_assert(in_range<float, f0, f1>(0.5f), "!");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With